在管道杀死前一个命令(Kill the previous command in a pipeline

2019-08-16 23:55发布

我运行一个仿真像这样

./waf --run scratch/myfile | awk -f filter.awk 

我怎么能杀waf尽快命令filter.awk检测到发生了什么事情(如特定行被读取之后)?

我不能改变wafmyfile 。 我只能改变filter.awk ,和上面的命令(显然)。

评论后更新:

  • waf接收后不终止SIGPIPE (因为它应该?)
  • 它生成的子进程,也需要清理。

这是我自己的答案 (和挑战)。


对@ thatotherguy的ANS工作@克里斯的回答后,我简化了一下,得到这个:

tmp=$(mktemp)
{ ./waf --run scratch/myfile & echo $! > "$tmp"; } | { awk -f filter.awk; pkill -P $(<$tmp); kill $(<$tmp); }

不幸的是我无法摆脱的tmp文件,千方百计通过PID作为变量失败。

我不会改变公认的答案(因为它是一个工作时, 真的需要它),但是+1的人,可以简化多。

Answer 1:

是什么让这个棘手的是, waf行为不端通过不退出管道破裂时,和它产生掀起了第二次的过程,我们也必须摆脱掉:

tmp=$(mktemp)
cat <(./waf --run scratch/myfile & echo $! > "$tmp"; wait) | awk -f filter.awk; 
pkill -P $(<$tmp)
kill $(<$tmp)
  • 我们使用<(process substitution)运行waf的背景和其PID写入到一个临时文件。
  • 我们用cat作为中介从这个过程中AWK中继数据,因为cat将退出在正确的管道坏了,让管道来完成。
  • 当管道的完成,我们杀死所有进程waf催生了(由家长PID)
  • 最后,我们杀waf本身。


Answer 2:

使用awkexit声明。 waf应该尽快退出的管连接它awk关闭。



Answer 3:

awk退出, waf得到一个SIGPIPE它试图写入输出接下来的时间,这应该引起它退出,除非谁写waf故意设置它忽略SIGPIPE迹象向它退出,在这种情况下,你必须杀死它手动kill或一些这样的。 就像是:

./waf --run scratch/myfile | ( awk -f filter.awk; killall waf )

您可能需要一个-KILL选项killall如果waf是忽略所有的退出信号。



文章来源: Kill the previous command in a pipeline