杀死管道中的上一个命令

use*_*001 5 linux bash awk waf ns-3

我正在运行这样的模拟

./waf --run scratch/myfile | awk -f filter.awk 
Run Code Online (Sandbox Code Playgroud)

如何waf在filter.awk检测到发生的事情后立即终止命令(例如,在读取特定行之后)?

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

评论后更新:

  • waf接收后不会终止SIGPIPE(应该如此?)
  • 它产生需要清理的子进程。

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


在处理@thatotherguy 的回答 @Chris 的回答之后,我简化了一点,得到了这个:

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

不幸的是,我无法摆脱该tmp文件,每次尝试将其PID作为变量传递都失败了。

我不会更改已接受的答案(因为它是在真正需要时起作用的答案),但是对于任何可以简化更多的人来说,+1。

tha*_*guy 2

让这个问题变得棘手的是,waf当管道破裂时,它会产生不退出的行为,并且它会产生第二个进程,我们也必须摆脱它:

tmp=$(mktemp)
cat <(./waf --run scratch/myfile & echo $! > "$tmp"; wait) | awk -f filter.awk; 
pkill -P $(<$tmp)
kill $(<$tmp)
Run Code Online (Sandbox Code Playgroud)
  • 我们用来在后台<(process substitution)运行并将其 pid 写入临时文件。waf
  • 我们使用cat作为中介将数据从该进程中继到 awk,因为cat当管道损坏时将正确退出,从而允许管道完成。
  • 当管道完成后,我们杀死所有waf已生成的进程(通过父 PID)
  • 最后我们自杀waf了。