二番煎じ(3番か?)だがこちらの記事を参考にしてdashでpipefailを作成してみる。
pipefail() {
local cmd= i=1 ret1 ret2
pipe_parse "$@" || {
eval "$cmd"
return
}
exec 4>&1
ret1=$(
exec 3>&1
{
eval "$cmd" 3>&-
echo $? >&3
} 4>&- | {
shift $i
pipefail "$@"
} 3>&- >&4 4>&-
)
ret2=$?
exec 4>&-
[ $ret2 -ne 0 ] && \
return $ret2 || return $ret1
}
pipe_parse() {
[ "$1" = '|' ] && return
cmd="$cmd \${$i}"
i=$((i+1))
shift
[ $# -gt 0 ] && pipe_parse "$@"
}
pipefailあるあるのEPIPE。
$ pipefail yes \|
> head -n 1 \|
> grep y
$ echo $?
141
最も右の0以外の戻り値がパイプライン全体の戻り値になる。
$ pipefail yes \|
> head -n 1 \|
> grep n
$ echo $?
1
個人的には一番左の復帰値がほしいことが多い。
pipefailの最後をこうすると左優先になる。
[ $ret1 -ne 0 ] && \
return $ret1 || return $ret2