为什么使用 grep -q 退出代码 141?

问题描述 投票:0回答:4

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

linux bash freebsd
4个回答
114
投票

这是因为一旦找到匹配项,

grep -q
就会立即以零状态退出。
zfs
命令仍在写入管道,但没有读取器(因为
grep
已退出),因此从内核向它发送了
SIGPIPE
信号,并以
141
状态退出。

您看到此行为的另一个常见地方是使用

head
。例如

$ seq 1 10000 | head -1
1

$ echo ${PIPESTATUS[@]}
141 0

在这种情况下,

head
读取第一行并终止,生成
SIGPIPE
信号,并且
seq
141
退出。

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


6
投票

我不熟悉

zfs list
,但我猜它抱怨其标准输出被关闭 -
grep -q
在找到匹配项时立即退出,与
grep
不同。


3
投票

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

grep -q 坦克 <(zfs list)

更新:我想是一样的,因为括号内运行的进程也会收到 sigpipe。


0
投票

你可以继续吃输出,例如:

command | { grep -q whatever; cat >/dev/null; }
© www.soinside.com 2019 - 2024. All rights reserved.