5

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?

4 Answers 4

5
#!/bin/sh
#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 -$!
1
  • 1
    Thanks a lot. This is what I was looking for. Your explanation is going to be very helpful.
    – Varun
    Oct 5, 2015 at 19:47
2

Add a shell call

sh -c "watch date > date.txt"

For more levels, add more shells around

1

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

#!/bin/bash
depth=${1:-3}
f(){
 let depth--
 if [ $depth -gt 0 ]
 then $0 $depth
 else sleep 999
 fi
}
f

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

0

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .