Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kill the previous command in a pipeline

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.

like image 949
user000001 Avatar asked Feb 15 '13 16:02

user000001


People also ask

How do you kill a pipeline?

Pipeline jobs can be stopped by sending an HTTP POST request to URL endpoints of a build. BUILD ID URL/stop - aborts a Pipeline. BUILD ID URL/term - forcibly terminates a build (should only be used if stop does not work). BUILD ID URL/kill - hard kill a pipeline.

Which command is used to kill or terminate the process *?

$ ps -fu user Terminate the process. When no signal is included in the kill command-line syntax, the default signal that is used is –15 (SIGKILL). Using the –9 signal (SIGTERM) with the kill command ensures that the process terminates promptly.

What does the kill PID command do?

The kill command sends a signal (by default, the SIGTERM signal) to a running process. This default action normally stops processes. If you want to stop a process, specify the process ID (PID) in the ProcessID variable.


2 Answers

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

like image 119
chepner Avatar answered Oct 01 '22 22:10

chepner


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.
like image 45
that other guy Avatar answered Oct 01 '22 22:10

that other guy