管道中的下一个程序可以看到上一个程序的退出代码吗?


8

我想制作这样的Bash脚本管道

prog1 | prog2

这样prog2可以看到prog1的退出代码,并根据该信息采取不同的行动。

这可能吗?


您能否在问题的另一部分阐述行为
devnull 2014年

由于用于实现管道的内部缓冲以及调度方式和方式,因此您对退出prog2时进展的控制有限。prog1prog1prog2
chepner 2014年

另请参阅[管道命令以什么顺序运行?](unix.stackexchange.com/q/37508)–
DK Bose

Answers:


4

普遍的答案是不。有可能甚至在开始prog2之前就退出prog1(显然,如果prog2实际读取一些输入(如果您在管道中使用它,则希望这样做)就不会发生)。绝对有可能prog2在此之前退出prog1;例如,当prog2某个搜索程序找到匹配项后立即退出时,这种情况就prog1可能发生,在这种情况下,可能还没有完成所有数据的生成。

没有直接的方法prog2可以检索prog1甚至退出的退出状态prog1。所有这一切prog2可以知道的是,prog1已经关闭了其管道,它可以在不死亡做结束。

如果要获取prog1from 的退出状态prog2,有两种常用方法:可以将其写入文件,也可以通过管道发送。可以将输出状态作为管道数据的最后一行发送。您必须确保不处理最后一行,直到您知道这是最后一行,即直到您尝试阅读下一行为止。

{ prog1; echo $?; } | 

这是一个示例,其中右侧是一个文本过滤器,该过滤器将包含“错误”一词的每一行变为红色。如果左侧出现故障,则右侧以相同状态退出。

{ prog1; echo $?; } | awk '
    NR != 1 {
        if (line ~ /[Ee][Rr][Rr][Oo][Rr]/) print "\033[31m" line "\033[0m";
        else print line;
    }
    {line = $0}
    END {exit($0)}
'

我正在尝试{ command; echo ${PIPESTATUS[@]}; } | sort | ...使退出状态排在第一位。都很有趣!

@illuminÉ只有${PIPESTATUS[@]}在的输出中排在其他任何东西之前,这才起作用command。如果command打印出一堆数字,或者它可以打印出任意文本,则您会遇到麻烦:您将无法从状态行中区分其输出。
吉尔(Gilles)'“ SO-别再作恶了”

谢谢,实际上,只有在命令的输出大声笑中不包含0的情况下,它才能成功地将成功状态排在最前面。Tgif /秒。

2

尽管您可以在某些特殊情况下(请参阅其他答案),但并非在每种情况下都可以。一些过滤器程序将继续运行,而其他过滤器程序将保留所有输出,将其一次释放,然后退出。

例如,“将继续前进”程序grep将作为服务器tail -f /var/log/some_log_filesort在管道中使用会导致“停顿”,因为sort它将收集输入,直到其前面的管道关闭为止。使用xargs会增加进一步的复杂性:程序是否由xargs流水线的一部分启动(可能启动许多实例)?


-1是因为您对合理化错误答案表示支持。
ctrl-alt-delor 2014年

@理查德·??布鲁斯的答案是正确的(尽管第二段有些令人困惑)。
吉尔(Gilles)'所以

1

答案:不直接。

@terdon说明了管道中的上一个命令的退出代码必须作为显式参数发送给下一个命令。

请记住,管道只是前一个命令的STDOUT到下一个命令的STDIN的映射;退出代码不会输出到STDOUT(或STDERR)。


1
-1是因为您对引用不正确的答案而不是说更多而感到支持。
ctrl-alt-delor 2014年

@richard足够公平……我应该仔细检查一下……如果我强迫自己在很累的时候回答一个问题,那会发生什么……
pepoluan 2014年

1

管道中的所有过程均在退出之前启动。因此,prog2可能必须在启动后获取此信息,也必须推迟处理直到prog1退出,这可能会使管道停止运行。在执行您的要求时似乎存在根本问题,而不是操作系统限制。

您可能需要考虑一个临时文件,或将结果放入变量中。

使用变量的少量数据示例。

tmp=$(prog1)
if test "z$PIPESTATUS" == "z0"
then
   
else
   
fi

您的推理存在差距。prog2通常在prog1完成之前启动,但是有一种方法可以让它在prog1运行时从其接收输出状态。
吉尔(Gilles)'所以

0

为了完成吉尔的回答

(prog1; echo $? > /tmp/prog1.status) | prog2

是一种方法。  prog2可以

  • 读取标准输入到最后,然后读取/tmp/prog1.status,或
  • /tmp/prog1.status在读取标准输入时,定期检查是否存在。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.