set -e
は、トップシェルと同じようにサブシェルにも影響があると思いました。どうやら、そうではありません。この:
(
set -e
false
true
) || echo false1
bash -ec '
set -e
false
true
' || echo false2
bash <<EOF || echo false3
set -e
false
true
EOF
bash <<EOF || echo false4
false
true
EOF
bash <<EOF || echo false5
false &&
true
EOF
プリント
false2
false3
false5
これはどこに文書化されていますか?すべてのコマンドを&&
で接続せずに(または各コマンドの後に|| exit $?
を実行せずに)エラーでサブシェルを終了させることはできますか?
編集:
私の特定のユースケースは次のようなものでした:
set -e
# ...
status=0
( false; true ) || status=$?
report_code $status
return $status
サブシェルの内容は私の実際のコードでした。これの問題は、常にステータスを0に設定し、||
を;
で置き換えると、外側のセット-eが原因で不要なエラー終了が発生することです。
私はそれを解決しました:
set -e
# ...
set +e
( false; true ); status=$?
set -e
report_code $status
return $status
私はこれを実行する必要がなかったと思いますが、すべての一般的なシェルは、この実行されたサブシェルとフォークされたサブシェルの二分法を示しているようです:
#!/bin/sh
echo FORK\'D:
export SH
for SH in dash bash ksh zsh; do
$SH -c 'st=0; ( set -e; false; true ) || st=$?; printf "%s\t%s\n" $SH $st; '
done
echo EXEC\'D:
for SH in dash bash ksh zsh; do
$SH -c 'st=0; '$SH' -c " set -e; false; true " || st=$?; printf "%s\t%s\n" $SH $st; '
done
出力:
FORK'D:
dash 0
bash 0
ksh 0
zsh 0
EXEC'D:
dash 1
bash 1
ksh 1
zsh 1
観察する:
$ ( set -e; false ; true ) || echo false1
$ ( set -e; false ; true ) ; echo code=$?
code=1
また:
$ ( set -e; false ; true; echo inside=$? ) || echo false1
inside=0
どうやら、サブシェルの後に||
が続いている場合、set -e
はfalse
コマンドに到達してもサブシェルを終了させません。代わりに、サブシェルはtrue
(およびecho inside=$?
)を続行して実行します。
set -e
の哲学は、通常、キャッチされないエラーが発生した場合にのみ終了することです。ここで、サブシェルの外側に||
が存在すると、サブシェル内のエラーが「キャッチ」され、false
の後にset -e
が終了しないことをシェルに伝えているようです。
set -e
には、多くの驚くべき動作があります。 「-eが設定されていないのはなぜですか?」)を参照してください
上記の動作は、man bash
のドキュメントに示されています。
-e
パイプライン(単一の単純なコマンドで構成される場合があります)、リスト、または複合コマンド(上記のシェルGRAMMARを参照)がゼロ以外のステータスで終了した場合は、すぐに終了します。 失敗したコマンドがコマンドリストの一部(whileまたはuntilキーワードの直後)、テストの一部(ifまたはElifの予約語、&=または||で実行されるコマンドの部分list最後の&&または||に続くコマンド、パイプライン内の最後以外のコマンド、またはコマンドの戻り値が!で反転されている場合を除く。 -eが無視されている間にコマンドが失敗したため、サブシェル以外の複合コマンドがゼロ以外のステータスを返した場合、シェルは終了しません。設定されている場合、ERRのトラップはシェルが終了する前に実行されます。このオプションは、シェル環境と各サブシェル環境に個別に適用され(上記のコマンド実行環境を参照)、サブシェル内のすべてのコマンドを実行する前にサブシェルが終了する可能性があります。 [強調が追加されました。]