web-dev-qa-db-ja.com

別のスクリプトのスクリプトを呼び出しますが、子がexitを呼び出した場合は親を終了しません

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

11
user3589887

ここでは、second.shthird.shを同じプロセスで実行されるサブスクリプトとして含めています。これは、シェルプログラミングでは「ソーシング」と呼ばれています。 . ./second.shは、基本的にその時点でsecond.shのテキストを含めることと同じです。 exitコマンドはプロセスを終了します。元のスクリプトで呼び出すか、ソーススクリプトで呼び出すかは関係ありません。

second.shthird.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.shthird.shで定義された変数または関数を使用する必要がある場合は、それらをソースし続ける必要があります。

returnビルトインは、プロセス全体ではなく、ソーススクリプトのみを終了します。これは、.コマンドに別のスクリプトを含めることと、親スクリプトにそのテキストを含めることの数少ない違いの1つです。ソーススクリプトが関数内ではなくトップレベルでのみexitを呼び出す場合は、exitreturnに変更できます。エイリアスを使用して、スクリプトを変更せずにそれを行うことができます。

#! /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

2番目と3番目のシェルをソースする代わりに、他のコマンドと同じように実行します。次のように、必要に応じて終了コードを保存して使用できます。

#! /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...
6
Dale Anderson

この方法で試してください(最初に削除してください.の呼び出し時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のショートコードで、2番目のスクリプトを最初のスクリプトの一部として含めます。

0