Antonio
Antonio

Reputation: 59

Killing multiple processes in bash upon a single ctrl+c input

My script executes three processes that run cyclically until they are interrupted. I run the first two in background and the last one in foreground.

#!/bin/bash

./p1 &
PID1=$!

./p2 | tee p2.log & 
PID2=$!

sleep 1
./p3 "$(head -1 p2.log)" | tee p2.log

kill -KILL $PID1 $PID2

I would like to know how to get that, once the foreground process receives an interruption signal (Ctrl + C), the rest of the processes ends their execution.

In principle, I have simply tried to use the kill -KILL command on the PIDs of the processes running in background, but when using pipes to redirect their outputs, an exception appears:

Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
./script.sh: line 15: kill: (9106) - The process does not exist
./script.sh: line 15: kill: (9104) - The process does not exist

Example cyclic process (p1, p2, p3) below:

#!/bin/bash

while true; do
    echo "Hello World"
    sleep 1
done

How can I use a single CTRL-C (^C) to kill multiple processes?

Upvotes: 1

Views: 2363

Answers (1)

topher217
topher217

Reputation: 1377

I'm not getting the same error as you, but you can trap the ctrl+c input, then do something with it, i.e. kill the first two processes. I edited your question to include the example cyclic processes (i.e. I used the same code for p1, p2, and p3) Please comment or edit this example code if something is dramatically different, or I am missing some component that led to your originally quoted error. Assuming these example p1, p2, p3 to be similar to what you used, your new central script would be:

#!/bin/bash

trap ctrl_c INT

function ctrl_c() {
    echo "Trapped CTRL_C"
    kill -KILL $PID1 $PID2
}

./p1 &
PID1=$!
echo "PID1=" $PID1

./p2 | tee p2.log &
PID2=$!
echo "PID2=" $PID2
sleep 1

./p3 "$(head -1 p2.log)" | tee p2.log

I added an echo of the PID1 and PID2 such that I could check in another terminal whether the process had actually been killed. To do so

  • Run the central script in one terminal
  • The PID values will be echoed
  • You can then check if they exist by ps [PID#] in a separate terminal.
  • After verifying they exist, go back to the original terminal and ctrl+c
  • Loops and pipes should stop
  • go back to 2nd terminal and ps [PID#] again to verify the processes have been killed

I took this solution from here but there are a few ways to go about it. See another syntax here

Upvotes: 1

Related Questions