A Weird Imagination

Kill child jobs on script exit

Posted in

The problem

When writing a shell script that starts background jobs, sometimes running those jobs past the lifetime of the script doesn't make sense. (Of course, sometimes background jobs really should keeping going after the script completes, but that's not the case this post is concerned with.) In the case that either the background jobs are used to do some background computation relevant to the script or the script can conceptually be thought of as a collection of processes, it makes sense for killing the script to also kill any background jobs it started.

The solution

At the start of the script, add

cleanup() {
    # kill all processes whose parent is this process
    pkill -P $$

for sig in INT QUIT HUP TERM; do
  trap "
    trap - $sig EXIT
    kill -s $sig "'"$$"' "$sig"
trap cleanup EXIT

If you really want to kill only jobs and not all child processes, use the kill_child_jobs() function from all.sh or look at the other versions in the kill-child-jobs repository.

The details

Read more…

Child process not in ps?

Posted in

A buggy program

Consider the following (contrived) program1 which starts a background process to create a file and then waits while the background process is still running before checking to see if the file exists:


# Make sure file doesn't exist.
rm -f file

# Create file in a background process.
touch file &
# While there is a touch process running...
while ps -C "touch" > /dev/null
    # ... wait one second for it to complete.
    sleep 1
# Check if file was created.
if [ -f file ]
    echo "Of course it worked."
    echo "Huh? File wasn't created."
    # Wait for background tasks to complete.
    if [ -f file ]
        echo "Now it's there!"
        echo "File never created."

# Clean up.
rm -f file

Naturally, it will always output "Of course it worked.", right? Run it in a terminal yourself to confirm this. But I claimed this program is buggy; there's more going on.

Read more…