我运行一个仿真像这样
./waf --run scratch/myfile | awk -f filter.awk
我怎么能杀waf
尽快命令filter.awk
检测到发生了什么事情(如特定行被读取之后)?
我不能改变waf
或myfile
。 我只能改变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的人,可以简化多。
是什么让这个棘手的是, 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
本身。
使用awk
的exit
声明。 waf
应该尽快退出的管连接它awk
关闭。
当awk
退出, waf
得到一个SIGPIPE
它试图写入输出接下来的时间,这应该引起它退出,除非谁写waf
故意设置它忽略SIGPIPE
迹象向它退出,在这种情况下,你必须杀死它手动kill
或一些这样的。 就像是:
./waf --run scratch/myfile | ( awk -f filter.awk; killall waf )
您可能需要一个-KILL
选项killall
如果waf
是忽略所有的退出信号。