パイプ処理の終了ステータスを取得する方法をまとめます。
はじめに
パイプ処理の終了ステータスを取得($?)すると、デフォルトでは一番最後のコマンドの終了ステータスのみが取得されます。
#!/bin/bash exit 1 | exit 2 | exit 0 echo $? # 出力: 0
パイプ内コマンドの終了ステータスはマスクされてしまうので、パイプ内の異常終了を検知したいときなどに不都合です。
今回は、パイプ処理内の各コマンドの終了ステータスを取得する方法をまとめます。
The English translation of this post is here.
パイプ処理の終了ステータスを取得する
PIPESTATUS を参照する方法
まずは、PIPESTATUSを使った方法です。
この変数には、実行されたパイプ処理内コマンドの終了ステータスが配列で格納されます。
${PIPESTATUS[@]}で参照すれば、パイプ処理内の全コマンドの終了ステータスが確認できます。
#!/bin/bash exit 1 | exit 2 | exit 0 echo "${PIPESTATUS[@]}" # 出力: 1 2 0
引数を渡して参照すれば、特定のパイプ処理内コマンドの終了ステータスを取得できます。
#!/bin/bash exit 1 | exit 2 | exit 0 echo "${PIPESTATUS[0]}" "${PIPESTATUS[1]}" # 出力: 1 2
set -o pipefail を利用した方法
次はset -o pipefailを利用した方法です。
set -o pipefailは、0以外の終了ステータスで終えた最後のコマンドの終了ステータスを、パイプ処理の終了ステータスとする設定です。
パイプ内コマンドの異常終了ステータスをマスクせずに取得することが出来るようになります。
setコマンドのman pageより引用:
the return value of a pipeline is the status of the last command to exit with a non-zero status, or zero if no command exited with a non-zero status
実際に実行してみると、以下のようにパイプ内の最後の異常終了ステータスが、パイプの終了ステータスとして取得されます。
#!/bin/bash set -o pipefail exit 1 | exit 2 | exit 0 echo $? # 出力: 2
おわりに
今回は、パイプ処理の終了ステータスを取得する方法をまとめました。
パイプ処理は非常に強力な機能なので、細かいハンドリングも含めて使い慣れていきたいものです。
[関連記事]