コマンドの実行でエラーが起こってないか監視ツールで監視したいため、
コマンドの実行が成功したか失敗するか取得する方法を調べました。
正常 or エラー
Linux(Unix)では、すべてのコマンドは終了コード(exit code)を返します。
0が成功、1以上の値はエラーです。
エラー時の終了ステータスは以下のように予約されています。
128+nのエラー内容はコマンドやソフトウェアの実装によって異なります。
| 終了ステータス | 意味 |
|---|---|
| 1 | 一般的なエラー |
| 2 | ビルトインコマンドの誤用 |
| 126 | コマンドを実行できなかった(実行権限がなかった) |
| 127 | コマンドが見つからなかった |
| 128 | exit に不正な値を渡した(例えば浮動小数点数) |
| 128+n | シグナル n で終了 |
| 255 | 範囲外の終了ステータス |
引用:
https://ja.wikipedia.org/wiki/%E7%B5%82%E4%BA%86%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9#bash
特殊変数 $?
直前に実行したコマンドの終了コードは$?という特殊変数に格納されています。
echo $?というコマンドを実行することで直前の終了コードを表示できます。
echoは引数の文字列や変数を表示するコマンドです。
パイプの終了ステータス
# exit 2 | exit 1 | exit 0
こういうケース。
3つのコマンドをパイプで繋いでいます。
1つめと2つめはエラーを返すようになっています。
上記のコマンドの実行後にecho $?とすると、0(正常終了)が返ってしまいました。
パイプ元でエラーが発生していても正常終了扱いになってしまうので注意が必要です。
(たぶん、最後に終了したコマンドの終了コードが帰ってきます。)
簡単な解決策は2つあります。
ただし、Bash,Zsh以外のシェルでも使えるか不明なので注意すること。
PIPESTATUS
# exit 2 | exit 1 | exit 0
# echo ${PIPESTATUS[@]}
2 1 0
PIPESTATUSという配列変数で取得できます。
set -o pipefail
pipefailを有効にすると、Pipeでエラーが有ったときそのエラーコードを返してくれます。
# set -o pipefail
# exit 2 | exit 1 | exit 0
# echo $?
2
関連:リダイレクトの終了ステータス
リダイレクト元かリダイレクト先のどちらかが終了ステータスを返したら
その終了ステータスを返します。
# echo aaa > .
# echo $?
1
# cat . > file.txt
# echo $?
1
※.はディレクトリなので、書き込めずエラーになります。