Trying to close all child processes when I interrupt my bash script

Viewed 3227

I have written a bash script to carry out some tests on my system. The tests run in the background and in parallel. The tests can take a long time and sometimes I may wish to abort the tests part way through.

If I Control+C then it aborts the parent script, but leaves the various children running. I wish to make it so that I can hit Control+C or otherwise to quit and then kill all child processes running in the background. I have a bit of code that does the job if I'm running running the background jobs directly from the terminal, but it doesn't work in my script.

I have a minimal working example.

I have tried using trap in combination with pgrep -P $$.

#!/bin/bash

trap 'kill -n 2 $(pgrep -P $$)' 2
sleep 10 &
wait

I was hoping that on hitting control+c (SIGINT) would kill everything that the script started but it actually says:

./breakTest.sh: line 1: kill: (3220) - No such process

This number changes, but doesn't seem to apply to any running processes, so I don't know where it is coming from.

I guess if the contents of the trap command get evaluated where the trap command occurs then it might explain the outcome. The 3220 pid might be for pgrep itself.

I'd appreciate some insight here

Thanks

3 Answers

I have found a solution using pkill. This example also deals with many child processes.

#!/bin/bash
trap 'pkill -P $$' SIGINT SIGTERM
for i in {1..10}; do
   sleep 10 &
done
wait

This appears to kill all the child processes elegantly. Though I don't properly understand what the issue was with my original code, apart from sending the correct signal.

in bash whenever you you use & after a command it places that command as a background job ( this background jobs are called job_spec ) which is incremented by one until you exit that terminal session. You can use the jobs command to get the list of the background jobs running. To work with this jobs you have to use the % with the job id. The jobs command also accept other options such as jobs -p to see the proces sids of all jobs , jobs -p %JOB_SPEC to see the process of id of that particular job.

#!/usr/bin/env bash

trap 'kill -9 %1' 2

sleep 10 &

wait

or

#!/usr/bin/env bash

trap 'kill -9 $(jobs -p %1)' 2

sleep 10 &

wait

I implemented something like this few years back, you can take a look at it async bash

You can try something like the following:

pkill -TERM -P <your_parent_id_here>
Related