Вызовите скрипт для другого скрипта, но не выходите из родительского, если ребенок вызывает 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 $?

Если second.shобнаруживает ошибку и выходит со статусом -9, first.shвыходит всегда. Как я могу избежать выхода из первой оболочки, если выходит дочерняя оболочка?

Я не могу редактировать second.sh.

user3589887
источник
Здесь вы используете .команду, которая создает другой файл в текущей оболочке. Здесь нет дочерней оболочки или вложенной оболочки. Вы имели в виду выполнить, second.sh а third.shне искать их?
Селада
да .. я должен написать выполнить вместо. ./? я хочу игнорировать "exit $?" внутри second.sh .. можно без редактирования second.sh?
user3589887

Ответы:

13

То, что вы делаете здесь, включает в себя second.shи в third.shкачестве вспомогательных сценариев, выполняющихся в одном и том же процессе, который называется «источником» в программировании оболочки. . ./second.shв основном эквивалентно включению текста second.shв этой точке. Команда exitзавершает процесс, не имеет значения, вызываете ли вы ее в исходном сценарии или в исходном сценарии.

Если все , что вы хотите сделать , это выполнить команды в second.shи third.shи они не должны получить доступ или изменить переменные и функции от оригинального сценария, называют эти сценарии в качестве дочерних процессов.

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

Если вам нужны другие сценарии для доступа к переменным и функциям из исходного сценария, но не для их изменения, то вызовите эти сценарии в подоболочках. Подоболочки - это отдельные процессы, поэтому exitвыходят только они.

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

Если вам нужно использовать переменные или функции, определенные в second.shи third.shв родительском скрипте, то вам нужно будет продолжать их поиск.

В returnBUILTIN выходит только найденный сценарий , а не весь процесс - это одна из немногих различий между включая другой скрипт с .командой , и в том числе его текста в родительском скрипте. Если исходные скрипты вызывают только exitна верхнем уровне, в отличие от внутренних функций, то вы можете перейти exitв return. Вы можете сделать это без изменения сценария, используя псевдоним.

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

Если exitтакже вызывается внутри функций, я не думаю, что есть не обременительный способ. Громоздкий способ - установить ловушку выхода и поместить туда свой код.

#!/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
Жиль "ТАК - прекрати быть злым"
источник
Именно по этой причине я перестал использовать '.' исходные файлы в сценарий, и вместо этого попробуйте использовать исключительно «источник». IMO, который следует считать bash «лучшей практикой», поскольку он делает намного более понятным, что делает ваш код.
Марк Э. Гамильтон
6

Вместо того чтобы использовать вторую и третью оболочки, просто запустите их, как и любую другую команду. Код выхода может быть сохранен и использован при необходимости, например, так:

#! /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...
Дейл Андерсон
источник
STATUS1=$?поймает результат ранее введенной команды эха, который не зависит от результата ./second.sh.
Cromax
@ Cromax ты совершенно прав. Ответ отредактирован.
Дейл Андерсон
0

Попробуйте это так (сначала удалите .при вызове 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 $?

Это потому, что .это шорткод, из-за sourceкоторого второй скрипт включается как часть первого.

Мойтаба Резаян
источник