Question

I am running a simulation like this

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

How can I kill the waf command as soon as filter.awk detects that something happened (e.g. after a specific line is read)?

I cannot change waf or myfile. I can only change filter.awk, and the above command (obviously).

Update after comments:

  • waf does not terminated after receiving SIGPIPE (as it should?)
  • It spawns child processes, that need cleaning up.

This is my own answer (and challenge).


After working on @thatotherguy's ans @Chris's answers, I simplified a bit and got this:

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

Unfortunately I could not get rid of the tmp file, every attempt to pass the PID as a variable failed.

I won't change the accepted answer (since it was the one that worked when it was really needed), but +1 for anyone that can simplify more.

Was it helpful?

Solution 2

What makes this tricky is that waf misbehaves by not exiting when the pipe breaks, and it spawns off a second process that we also have to get rid off:

tmp=$(mktemp)
cat <(./waf --run scratch/myfile & echo $! > "$tmp"; wait) | awk -f filter.awk; 
pkill -P $(<$tmp)
kill $(<$tmp)
  • We use <(process substitution) to run waf in the background and write its pid to a temp file.
  • We use cat as an intermediary to relay data from this process to awk, since cat will exit properly when the pipe is broken, allowing the pipeline to finish.
  • When the pipeline's done, we kill all processes that waf has spawned (by Parent PID)
  • Finally we kill waf itself.

OTHER TIPS

Use awk's exit statement. waf should exit as soon as the pipe connecting it to awk closes.

When awk exits, waf gets a SIGPIPE the next time it tries to write output, which should cause it to exit unless whoever wrote waf deliberately set it up to ignore SIGPIPEs telling it to exit, in which case you'll have to kill it manually with kill or some such. Something like:

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

You might need a -KILL option to killall if waf is ignoring all exit signals.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top