5

我正在运行这样的模拟

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

waf一旦filter.awk检测到发生了某些事情(例如在读取特定行之后),我如何才能终止命令?

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

评论后更新:

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

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


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

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

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

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

4

3 回答 3

4

使用awk'exit语句。waf应在连接它的管道awk关闭后立即退出。

于 2013-02-15T16:50:22.587 回答
2

让这件事变得棘手的是,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了。
于 2013-02-15T19:12:33.667 回答
1

awk退出时,在下次尝试写入输出时waf获取 a ,这应该导致它退出,除非编写者故意将其设置为忽略s 告诉它退出,在这种情况下,您必须手动杀死它或类似的东西. 就像是:SIGPIPEwafSIGPIPEkill

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

如果忽略所有退出信号,您可能需要一个-KILL选项。killallwaf

于 2013-02-15T17:15:08.033 回答