次のスクリプトには、構文エラーまたはある種のエラーがあります。
#!/usr/bin/env bash
set -euo pipefail
if [ ! -f /custom.log]; then
echo "test"
fi
abcxyz
スクリプトは次の出力で失敗します:
./test.sh: line 4: [: missing `]'
./test.sh: line 7: abcxyz: command not found
このスクリプトを修正する方法は心配していませんが、このエラーが発生した場合にスクリプトが続行されないようにするにはどうすればよいですか? set -e
はこの動作を強制します。
set -e
は、if
/while
/until
構成要素の条件セクションや||
、&&
の左側などの条件として使用される失敗したコマンドではトリガーされません。関数、サブシェル、ソースファイル、eval
edコードで、これらの条件下で呼び出されます。
もしそうなら、それから:
if [ ! -f /custom.log ]; then
/custom.log
もゼロ以外の終了ステータスで終了するため、[
が通常のファイルである場合はスクリプトを終了します。
bash
シェル(および他のほとんどの実装)の[
組み込みコマンドは、テストされた条件が満たされていない場合は1
ステータスで終了し、構文エラーがある場合は2
で終了します(ただし、すべての構文エラーではありませんが、 [ -v 'a[+]' ]
内)。 POSIXでは、エラーの場合、終了ステータスが1より大きい必要があります 。
したがって、条件で使用されているかどうかに関係なく、コマンドが1より大きいコードで終了する場合は、次のようなものでスクリプトを終了することを選択できます。
shopt -s extdebug # make sure the DEBUG trap propagates to subshells
trap '(($?>1 && (ret=$?))) && exit "$ret"' DEBUG
[ -f / ] || echo / not a regular file # OK
[ -f /] || echo was a syntax error # causes an exit, not output
echo not reached
ERR
トラップは、set -e
によって終了をトリガーする条件と同じ条件でのみ実行されるため、そのためにERR
トラップを使用できないことに注意してください。
ここで、その影響に注意してください。例えば、それは以下を引き起こします:
if grep -qs pattern /file; then
echo pattern was found in /file
fi
/file
が存在しない、または読み込めなかった場合に終了します。grep
は、2つのステータスで返されます。ただし、-s
では、これらのケースを無視することを明確に意図していました。
したがって、条件で使用するコマンドが1より大きいステータスで終了する可能性がある条件に注意する必要があります。これらを回避するには、次のようなものが必要です。
if sh -c 'grep -sq pattern / file || exit 1'; then...
1以上の終了ステータスで終了を[
またはtest
コマンドに制限することもできます。
unset -v previous_BASH_COMMAND
trap '
case $previous_BASH_COMMAND in
("[ "* | "test "*) (($?>1 && (ret=$?))) && exit "$ret"
esac
previous_BASH_COMMAND=$BASH_COMMAND' DEBUG
これにはいくつかの制限があります。に
echo x
([ -f/]; echo y)
$previous_BASH_COMMAND
がそこに設定されていないため、サブシェルは終了しますが、親は終了しません。そしてで:
[ -f / ] && echo a regular file
(grep -qs foo /file && echo foo in /file)
echo here
echo here
が2で、$?
が$previous_BASH_COMMAND
だったため、[ -f / ]
を実行するとシェルが終了します。
とにかく、
[ -f /] | cat
export var="$([ -f /])"
終了ステータスが親シェルプロセスに伝達されないため、検出できませんでした(最初のケースのpipefail
オプションを除く)。
現在、開発時に(スクリプトを記述してテストするときに)エラーを簡単に検出できる場合、実行時にこの種の(もろい)検出を追加するのに問題があるかどうかはわかりません。