パイプ処理の終了ステータスを取得する方法をまとめます。
はじめに
こんにちは、@bioerrorlogです。
パイプ処理の終了ステータスを取得($?
)すると、デフォルトでは一番最後のコマンドの終了ステータスのみが取得されます。
#!/bin/bash exit 1 | exit 2 | exit 0 echo $? # 出力: 0
パイプ内コマンドの終了ステータスはマスクされてしまうので、パイプ内の異常終了を検知したいときなどに不都合です。
今回は、パイプ処理内の各コマンドの終了ステータスを取得する方法をまとめます。
環境
bash
での実行を前提としています。
パイプ処理の終了ステータスを取得する
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
おわりに
今回は、パイプ処理の終了ステータスを取得する方法をまとめました。
パイプ処理は非常に強力な機能なので、細かいハンドリングも含めて使い慣れていきたいものです。
[関連記事]
参考
shell - Get exit status of process that's piped to another - Unix & Linux Stack Exchange