web-dev-qa-db-ja.com

なぜgrep -qでコード141を終了するのですか?

誰かが以下から終了コード141を取得する理由を説明できますか?

#!/usr/bin/bash

set -o pipefail

zfs list | grep tank
echo a ${PIPESTATUS[@]}

zfs list | grep -q tank
echo b ${PIPESTATUS[@]}

cat /etc/passwd | grep -q root
echo c ${PIPESTATUS[@]}

私は得る

...
a 0 0
b 141 0
c 0 0

私の理解では終了コード141は失敗ですが、上記の行はゼロを示しているため、成功するはずです。

32

これは、一致が見つかるとすぐにgrep -qがゼロステータスですぐに終了するためです。 zfsコマンドはまだパイプに書き込みを行っていますが、リーダーが存在しないため(grepが終了したため)、カーネルからSIGPIPE信号が送信されて終了します。ステータスは141です。

この動作が見られるもう1つの一般的な場所は、headです。例えば.

$ seq 1 10000 | head -1
1

$ echo ${PIPESTATUS[@]}
141 0

この場合、headは最初の行を読み取って終了し、SIGPIPEシグナルを生成し、seq141で終了しました。

The Linux Programmer's Guideの「 The Infamous SIGPIPE Signal 」を参照してください。

51
dogbane

私はzfs listに精通していませんが、標準出力が閉じられていると文句を言います-grepとは異なり、一致が見つかるとすぐにgrep -qは終了します。

5
volferine

別のオプションは、パイプを使用せずに、プロセス置換を使用することです。

grep -q tank <(zfsリスト)

更新:括弧内で実行されるプロセスもsigpipeを受け取るため、同じことだと思います。