Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to kill all children of the current shell on interrupt?

My scripts cdist-deploy-to and cdist-mass-deploy (from cdist configuration management) run interactively (i.e. are called by a user).

These scripts call a lot of scripts, which again call some scripts:

cdist-mass-deploy ...
   cdist-deploy-to ...
       cdist-explorer-run-global ...
           cdist-dir ....

What I want is to exit / kill all scripts, as soon as cdist-mass-deploy is either stopped by control C (SIGINT) or killed with SIGTERM.

cdist-deploy-to can also be called interactively and should exhibit the same behaviour.

Using ps -ef... and co variants to find out all processes with the ppid looks like it could be quite unportable. Using $! does not work as in the deeper levels the children are no background processes.

I tried using the following code:

__cdist_kill_on_interrupt()
{
   __cdist_tmp_removal
   kill 0
   exit 1
}

trap __cdist_kill_on_interrupt INT TERM

But this leads to ugly Terminated messages as well as to a segfault in the shells (dash, bash, zsh) and seems not to stop everything instantly anyway:

# cdist-mass-deploy -p ikq04.ethz.ch ikq05.ethz.ch
core: Waiting for cdist-deploy-to jobs to finish
^CTerminated
Terminated
Terminated
Terminated
Segmentation fault

So the question is, how to cleanly exit including all (sub-)children in a portable manner (bourne shell, no csh support needed)?

like image 815
Nico Avatar asked Jun 08 '11 19:06

Nico


People also ask

Does killing a process kill all child processes?

Killing a parent doesn't kill the child processes Every process has a parent. We can observe this with pstree or the ps utility. The ps command displays the PID (id of the process), and the PPID (parent ID of the process).

How do I close the current shell?

To interrupt the current command press CTRL-C . If the bottom-left of your shell window shows --More-- you are viewing a file using more . To exit from more press q . If the bottom-left of your shell window shows filename , : or (END) you are viewing a file using less .

How do you kill a running shell script?

Assuming it's running in the background, under your user id: use ps to find the command's PID. Then use kill [PID] to stop it. If kill by itself doesn't do the job, do kill -9 [PID] . If it's running in the foreground, Ctrl-C (Control C) should stop it.


1 Answers

You don't need to handle ^C, that will result in a signal being sent to the whole process group, which will kill all the processes that are not in the background. So you don't need to catch INT.

The only reason you get a Terminated when you kill them is that kill sends TERM by default, but that's reasonable if you are handling a TERM in the first place. You could use kill -INT 0 if you want to avoid the messages.

(responding with extra info)

If the child processes are run in the background, you can get their process ids just after you start them, using the $! special shell variable. Gather these together in a variable and just kill them all when you need to terminate.

like image 120
chrisdowney Avatar answered Sep 20 '22 13:09

chrisdowney