#This is a process with an id of $$
( sleep 1000 )& #this creates an idle child
( (sleep 1000)& sleep 1000 )& #this creates an idle child and grandchild
wait #this waits for direct children to finish
Running the above as
./1.sh & on my system created the following process tree:
$ command ps -o pid,ppid,pgrp,stat,args,wchan --forest
PID PPID PGRP STAT COMMAND WCHAN
24949 4783 24949 Ss /bin/bash wait
25153 24949 25153 S \_ /bin/sh ./1.sh sigsuspend
25155 25153 25153 S | \_ sleep 1000 hrtimer_nanosleep
25156 25153 25153 S | \_ sleep 1000 hrtimer_nanosleep
25158 25156 25153 S | \_ sleep 1000 hrtimer_nanosleep
You can notice that the tree has the same process group (PGRP) of 25153, which is identical to the PID of the first process.
The shell creates a process group whenever you start a new command in interactive mode (or with job control explicitly turned on).
The PGRP mechanism allows the shell to send a signal to the whole process group at once without creating a race condition. This is used for job control, and when your script runs and a foreground job, for sending:
- (SIG)INTR when the user presses C-C
- (SIG)QUIT when the user presses C-\
- (SIG)STP when the user presses C-Z
You can do the same by doing, for example:
kill -INTR -25153
where INTR is the signal and 25153 is the process group you want to send the signal to. The
- before the 25153 means you're targeting a PGRP id rather than a PID.
In your case, the signal you should be sending is
-TERM (request termination). Term is the default signal
kill sends, however, you have to specify it explicitly if you're targeting a group rather than a PID.
kill -TERM -25153
If you want to kill the process group of the last background job you started, you can do:
kill -TERM -$!