web-dev-qa-db-ja.com

コマンドがゼロ以外の値を返した場合にシェルスクリプトを中止する

いくつかのコマンドを呼び出すBash Shellスクリプトがあります。いずれかのコマンドがゼロ以外の値を返す場合は、シェルスクリプトを自動的に終了値1で終了させます。

各コマンドの結果を明示的にチェックしなくてもこれは可能ですか?

例えば.

dosomething1
if [[ $? -ne 0 ]]; then
    exit 1
fi

dosomething2
if [[ $? -ne 0 ]]; then
    exit 1
fi
383
Jin Kim

これをスクリプトの先頭に追加します。

set -e

これにより、単純なコマンドがゼロ以外の終了値で終了した場合に、シェルは直ちに終了します。単純なコマンドは、if、while、またはuntilテストの一部ではないコマンド、または&&または||の一部ではないコマンドです。リスト。

詳細は、 "set"内部コマンドの bash(1)のマニュアルページ を参照してください。

私は個人的にはほとんどすべてのシェルスクリプトを "set -e"で始めます。途中で何かが失敗して、スクリプトの残りの部分の仮定を破ったときに、スクリプトを頑固に継続させるのは本当に面倒です。

664
Ville Laurikari

承認された回答に追加するには:

特にパイプがある場合は、set -eだけでは不十分な場合があることに注意してください。

たとえば、このスクリプトがあるとします。

#!/bin/bash
set -e 
./configure  > configure.log
make

... configureのエラーは実行を中止します。

明日あなたは一見些細な変更を加えます。

#!/bin/bash
set -e 
./configure  | tee configure.log
make

...そして今はうまくいきません。これは ここ で説明されており、回避策(Bashのみ)が提供されています。

#!/ bin/bash 
 set -e 
set -o pipefail
 
 ./ configure | tee configure.log 
 make 
181
leonbloy

あなたの例のif文は不要です。このようにしてください。

dosomething1 || exit 1

Ville Laurikariのアドバイスを受けてset -eを使用する場合、いくつかのコマンドではこれを使用する必要があります。

dosomething || true

|| trueは、コマンドが失敗してもコマンドパイプラインにtrueの戻り値を持たせるため、-eオプションを指定してもスクリプトは強制終了されません。

74
Zan Lynx

終了時にクリーンアップが必要な場合は、擬似シグナルERRとともに 'trap'を使用することもできます。これはINTや他の信号を捕捉するのと同じように機能します。いずれかのコマンドがゼロ以外の値で終了すると、bashはERRをスローします。

# Create the trap with   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah

または、特に "set -e"を使用している場合は、EXITをトラップする可能性があります。正常終了、割り込み、-eオプションによる終了など、何らかの理由でスクリプトが終了すると、トラップが実行されます。

27
fholo

先頭に-eまたはset -eを付けて実行します。

set -uも見てください。

12
lumpynose

$?変数はめったに必要とされません。擬似イディオムcommand; if [ $? -eq 0 ]; then X; fiは常にif command; then X; fiと書く必要があります。

$?が必要な場合は、複数の値に対してチェックする必要がある場合です。

command
case $? in
  (0) X;;
  (1) Y;;
  (2) Z;;
esac

あるいは$?を再利用する必要がある場合、またはその他の方法で操作する必要がある場合は、次のようにします。

if command; then
  echo "command successful" >&2
else
  ret=$?
  echo "command failed with exit code $ret" >&2
  exit $ret
fi
10
Mark Edgar
#!/bin/bash -e

十分なはずです。

3
Baligh Uddin

のような表現

dosomething1 && dosomething2 && dosomething3

コマンドの1つがゼロ以外の値で戻ったときに処理を停止します。たとえば、次のコマンドは "done"を印刷しません。

cat nosuchfile && echo "done"
echo $?
1
3
gabor