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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19120263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:59:35  来源:igfitidea点击:

Why exit code 141 with grep -q?

linuxbashfreebsd

提问by Sandra Schlichting

Can someone explain why I get exit code 141 from the below?

有人可以解释为什么我从下面得到退出代码 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[@]}

I get

我得到

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

From my understanding exit code 141 is a failure, but the line above gives zero, so it should be success, I would say.

根据我的理解,退出代码 141 是失败的,但上面的行给出了零,所以我会说它应该是成功的。

采纳答案by dogbane

This is because grep -qexits immediately with a zero status as soon as a match is found. The zfscommand is still writing to the pipe, but there is no reader (because grephas exited), so it is sent a SIGPIPEsignal from the kernel and it exits with a status of 141.

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

Another common place where you see this behaviour is with head. e.g.

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

$ seq 1 10000 | head -1
1

$ echo ${PIPESTATUS[@]}
141 0

In this case, headread the first line and terminated which generated a SIGPIPEsignal and seqexited with 141.

在这种情况下,head读取第一行并终止它生成一个SIGPIPE信号并seq退出141

See "The Infamous SIGPIPE Signal" from The Linux Programmer's Guide.

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

回答by volferine

I'm not familiar with zfs list, but I guess it complains about its standard output being closed - grep -qexits immediately when a match is found, unlike grep.

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

回答by Elizandro - SparcBR

Another option would be to not use a pipe, but use a process substitution:

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

grep -q tank <(zfs list)

grep -q tank <(zfs 列表)

Update: I guess is the same thing, as the process run inside parentheses will also receive sigpipe.

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