【问题标题】:Why exit code 141 with grep -q?为什么用 grep -q 退出代码 141?
【发布时间】:2013-10-07 20:29:09
【问题描述】:

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


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      $ seq 1 10000 | head -1
      1
      
      $ echo ${PIPESTATUS[@]}
      141 0
      

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

      请参阅《Linux 程序员指南》中的“The Infamous SIGPIPE Signal”。

      【讨论】:

      • 通常,退出状态 N 大于 128 表示程序被信号 N - 128 终止。由于SIGPIPE 是信号 13, 141 - 128 = 13 表示您的程序以SIGPIPE 结束。
      • 有没有办法我仍然可以使用 set -o pipefailgrep -q,因为我想保留它,因为我有很多来自 SSH 的解析。
      • @chepner:这不是惯例问题,而是 shell 如何处理因信号而退出的进程的问题。对于 bash,它是 128 + signal_number,但其他 shell 使用其他公式。看到这篇精彩的帖子:unix.stackexchange.com/a/99134/9041
      • @SandraSchlichting:请参阅Effective SIGPIPE handling,了解 bash 中的 pipefail 问题及其替代方法。
      • @SandraSchlichting:我也有同样的问题,很烦人。一个想法:不要将-q 选项与grep 一起使用,而是重定向输出:1> /dev/null 2>&1。理论上,grep 处理整个输入的速度稍慢,但实际上:它可以工作。
      【解决方案3】:

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

      grep -q tank

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

      【讨论】:

        猜你喜欢
        • 2014-12-02
        • 1970-01-01
        • 2020-11-17
        • 2011-03-31
        • 1970-01-01
        • 1970-01-01
        • 2019-10-03
        • 2019-10-12
        • 1970-01-01
        相关资源
        最近更新 更多