For testing purposes I have this shell script
#!/bin/bash
echo $$
find / >/dev/null 2>&1
Running this from an interactive terminal, ctrl+c will terminate bash, and the find command.
$ ./test-k.sh
13227
<Ctrl+C>
$ ps -ef |grep find
$
Running it in the background, and killing the shell only will orphan the commands running in the script.
$ ./test-k.sh &
[1] 13231
13231
$ kill 13231
$ ps -ef |grep find
nos 13232 1 3 17:09 pts/5 00:00:00 find /
$
I want this shell script to terminate all its child processes when it exits regardless of how it's called. It'll eventually be started from a python and java application - and some form of cleanup is needed when the script exits - any options I should look into or any way to rewrite the script to clean itself up on exit?
If you are executing a Bash script in your terminal and need to stop it before it exits on its own, you can use the Ctrl + C combination on your keyboard.
There are many methods to quit the bash script, i.e., quit while writing a bash script, while execution, or at run time. One of the many known methods to exit a bash script while writing is the simple shortcut key, i.e., “Ctrl+X”. While at run time, you can exit the code using “Ctrl+Z”.
To interrupt it, you can try pressing ctrl c to send a SIGINT. If it doesn't stop it, you may try to kill it using kill -9 <pid> , which sends a SIGKILL.
I would do something like this:
#!/bin/bash
trap : SIGTERM SIGINT
echo $$
find / >/dev/null 2>&1 &
FIND_PID=$!
wait $FIND_PID
if [[ $? -gt 128 ]]
then
kill $FIND_PID
fi
Some explanation is in order, I guess. Out the gate, we need to change some of the default signal handling. :
is a no-op command, since passing an empty string causes the shell to ignore the signal instead of doing something about it (the opposite of what we want to do).
Then, the find
command is run in the background (from the script's perspective) and we call the wait
builtin for it to finish. Since we gave a real command to trap
above, when a signal is handled, wait
will exit with a status greater than 128. If the process wait
ed for completes, wait
will return the exit status of that process.
Last, if the wait
returns that error status, we want to kill
the child process. Luckily we saved its PID. The advantage of this approach is that you can log some error message or otherwise identify that a signal caused the script to exit.
As others have mentioned, putting kill -- -$$
as your argument to trap
is another option if you don't care about leaving any information around post-exit.
For trap
to work the way you want, you do need to pair it up with wait
- the bash
man page says "If bash
is waiting for a command to complete and receives a signal for which a trap
has been set, the trap
will not be executed until the command completes." wait
is the way around this hiccup.
You can extend it to more child processes if you want, as well. I didn't really exhaustively test this one out, but it seems to work here.
$ ./test-k.sh &
[1] 12810
12810
$ kill 12810
$ ps -ef | grep find
$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With