技術メモのかけら

内容はもとより調べたことすら忘れてしまうので個人的なメモです。とにかく短く、結論だけ書いていきます。

bashのpipefailオプション

以前から set -e を使って、エラー時に実行を止めるシェルをよく書いてましたが、
パイプでコマンドを繋げた場合、最後のコマンドにしか効かないことを今更ながら知ったのでメモ。

例えば、以下のシェルはslなんてコマンドは存在しないので、そこでエラーになり止まると思いきや、、、

#!/bin/bash

set -e

sl | echo "パイプの最後のコマンド"
echo "戻り値を確認:$?" 
echo "ここには来ないはず"

後続の処理が実行されてしまいました。

$ bash /tmp/sete.sh
パイプの最後のコマンド
/tmp/sete.sh: 行 5: sl: コマンドが見つかりません
戻り値を確認:0
ここには来ないはず

パイプの最後のechoが正常終了してるので、パイプ実行直後の$?が0となり後続が実行されるようです。

次にset -eの行をset -eo pipefailに変えて実行してみます。

$ bash /tmp/sete.sh
/tmp/sete.sh: 行 5: sl: コマンドが見つかりません
パイプの最後のコマンド

今度はパイプの最後までは実行されるが、後続処理は実行されませんでした。
上記を実行直後に$?を確認すると、コマンドが見つからない旨のエラーコード127が返っているので処理が止まるようです。

今度は、2箇所でエラーになるように絶対にヒットしないgrep detarameを追加してみます。

sl | grep detarame | echo "パイプの最後のコマンド"
$ bash /tmp/sete.sh
パイプの最後のコマンド
/tmp/sete.sh: 行 5: sl: コマンドが見つかりません

こんどは実行直後の$?は1だったので、最後にエラーになったgrepコマンドの戻り値がパイプの戻り値になるようです。