Wywołaj skrypt dla innego skryptu, ale nie wychodź z obiektu nadrzędnego, jeśli dziecko wywoła polecenie exit

11

first.sh:

#! /bin/ksh
echo "prova"
. ./second.sh
echo "ho lanciato il secondo"
. ./third.sh
echo "ho lanciato il terzo"

second.sh:

echo "sono nel secondo script"
dosomething1
exit $?

Jeśli second.shwykryje błąd i wyjdzie ze statusem -9, first.shkończy zawsze. Jak mogę uniknąć wychodzenia z pierwszej powłoki, jeśli powłoka potomna zostanie zamknięta?

Nie mogę edytować second.sh.

użytkownik3589887
źródło
Tutaj używasz .polecenia, które pobiera inny plik w bieżącej powłoce. Nie ma w tym żadnej powłoki potomnej ani podpowłoki. Czy chodziło Ci się wykonać second.sh i third.shzamiast ich pozyskiwania?
Celada
tak .. muszę napisać wykonać zamiast. ./? chcę zignorować „exit $?” wewnątrz second.sh .. jest możliwe bez edycji second.sh?
user3589887,

Odpowiedzi:

13

To, co tutaj robisz, obejmuje second.shi third.shjako skrypty działające w tym samym procesie, co w programowaniu powłoki nazywa się „pozyskiwaniem”. . ./second.shjest w zasadzie równoważne z dołączeniem tekstu second.shw tym momencie. exitKomenda zakończy procedurę, to nie ma znaczenia, czy to nazwać w oryginalnym skrypcie lub pozyskiwane w skrypcie.

Jeśli wszystko, co chcesz zrobić, to uruchomić polecenia second.shi third.shnie muszą one uzyskiwać dostępu ani modyfikować zmiennych i funkcji z oryginalnego skryptu, wywołaj te skrypty jako procesy potomne.

#! /bin/ksh
echo "prova"
./second.sh
echo "ho lanciato il secondo"
./third.sh
echo "ho lanciato il terzo"

Jeśli potrzebujesz innych skryptów, aby uzyskać dostęp do zmiennych i funkcji z oryginalnego skryptu, ale ich nie modyfikować, wywołaj te skrypty w podpowłokach. Podkładki są oddzielnymi procesami, więc zamykają exittylko je.

#! /bin/ksh
echo "prova"
(. ./second.sh)
echo "ho lanciato il secondo"
(. ./third.sh)
echo "ho lanciato il terzo"

Jeśli trzeba użyć zmiennych lub funkcji zdefiniowanych w second.sha third.shw skrypcie macierzystej, a następnie trzeba je zachować pozyskiwania.

Do returnwyjścia wbudowane tylko pozyskiwane skrypt i nie cały proces - to jeden z niewielu różnic między tym inny skrypt z .poleceniem i tym swój tekst w skrypcie macierzystej. Jeśli pozyskane skrypty wywołują tylko exitna najwyższym poziomie, w przeciwieństwie do funkcji wewnętrznych, możesz zmienić exitna return. Możesz to zrobić bez modyfikowania skryptu za pomocą aliasu.

#! /bin/ksh
echo "prova"
alias exit=return
. ./second.sh
echo "ho lanciato il secondo"
. ./third.sh
unalias exit
echo "ho lanciato il terzo"

Jeśli exitnazywane są również funkcjami wewnętrznymi, nie sądzę, że istnieje nieporęczny sposób. Uciążliwym sposobem jest ustawienie pułapki wyjścia i umieszczenie tam kodu.

#!/bin/ksh
do_first () {
  echo "prova"
  trap "after_second" EXIT
  . ./second.sh
  after_second
}
after_second () {
  echo "ho lanciato il secondo"
  trap "after_third" EXIT
  . ./third.sh
  after_third
}
after_third () {
  trap - EXIT
  echo "ho lanciato il terzo"
}
do_first
Gilles „SO- przestań być zły”
źródło
Z tego powodu przestałem używać „”. aby pobrać pliki do skryptu i zamiast tego spróbuj użyć wyłącznie „źródła”. IMO, które należy uznać za „najlepszą praktykę” bash, ponieważ dzięki temu znacznie wyraźniejsze jest to, co robi Twój kod.
Mark E. Hamilton
6

Zamiast pozyskiwać drugą i trzecią powłokę, po prostu uruchom je tak, jak inne polecenia. Kod wyjścia można zapisać i wykorzystać, jeśli zajdzie taka potrzeba:

#! /bin/ksh
echo "prova"

# execute and capture stdout ... output of second is not seen ...
OUTPUT1=$(./second.sh)

# find out exit status of second.sh
STATUS1=$?

# ... until now
echo $OUTPUT1

# do something based on the result
if [ $STATUS1 -eq 0 ]; then 
  echo "second.sh ran successfully"
else 
  echo "second.sh crapped out"
fi

# and so on...
Dale Anderson
źródło
STATUS1=$?wyłapie wynik poprzednio wydanej komendy echo, która jest niezależna od wyniku ./second.sh.
Cromax
@Cromax masz całkowitą rację. Odpowiedź została edytowana.
Dale Anderson
0

Wypróbuj w ten sposób (najpierw usuń .podczas rozmowy second.sh):

first.sh:

#! /bin/ksh
echo "prova"
./second.sh
echo "ho lanciato il secondo"
./third.sh
echo "ho lanciato il terzo"

second.sh:

echo "sono nel secondo script"
dosomething1
exit $?

Wynika to z faktu, że .jest to krótki kod, dla sourcektórego drugi skrypt jest dołączany jako część pierwszego.

Mojtaba Rezaeian
źródło