61

有人可以解释为什么我从下面得到退出代码 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 是失败的,但上面的行给出了零,所以我会说它应该是成功的。

4

3 回答 3

89

这是因为grep -q一旦找到匹配项,就会立即以零状态退出。该zfs命令仍在写入管道,但没有读取器(因为grep已退出),因此它SIGPIPE从内核发送一个信号,并以状态退出141

您看到此行为的另一个常见位置是使用head. 例如

$ seq 1 10000 | head -1
1

$ echo ${PIPESTATUS[@]}
141 0

在这种情况下,head读取第一行并终止,它生成一个SIGPIPE信号并seq141.

请参阅《 Linux 程序员指南》中的“臭名昭著的 SIGPIPE 信号”。

于 2013-10-01T15:51:59.187 回答
6

我不熟悉zfs list,但我猜它抱怨它的标准输出被关闭 -grep -q找到匹配时立即退出,不像grep.

于 2013-10-01T15:39:49.327 回答
3

另一种选择是不使用管道,而是使用进程替换:

grep -q 坦克 <(zfs 列表)

更新:我猜是同样的事情,因为括号内运行的进程也会收到 sigpipe。

于 2019-06-02T00:20:43.353 回答