I have some code that kills processes and their children/grandchildren. I want to test this code.

Currently I'm doing $ watch date > date.txt, which creates a process with a child.

Is there any way to create a parent -> child -> grandchild tree? What command can make that happen?

#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 -$!
| improve this answer | |
  • 1
    Thanks a lot. This is what I was looking for. Your explanation is going to be very helpful. – Varun Oct 5 '15 at 19:47

Add a shell call

sh -c "watch date > date.txt"

For more levels, add more shells around

| improve this answer | |

You can create a recursive script. eg in file /tmp/run

 let depth--
 if [ $depth -gt 0 ]
 then $0 $depth
 else sleep 999

then chmod +x /tmp/run and do /tmp/run 3.

| improve this answer | |

The ps command on freebsd doesn't seem to be able to produce a process tree. Fortunately there is a package called pstree which contains a program that will do precisely that.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.