3

I have a shell script that starts a couple of background child processes. I want them to always be running - unless the parent process quits or gets killed (so I have the children in a loop that just always restarts if it quits).

This script seems to work relatively well, if I execute it directly. But as soon as I sudo it, it will not clean up the other processes properly:

#!/bin/bash

trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT

# Start first background thing
while true;
do
        sleep 1
        echo "SOME PROCESS RUNNING IN THE BACKGROUND"
        echo "SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES"
        sleep 5
done &

# Start second background thing
while true;
do
        sleep 3
        echo "ANOTHER ONE..."
        sleep 3
done &

# Wait for quit keypress
while true
do
        echo "Press 'Q' to quit"
        read -rsn1
        if [ $REPLY == "q" ] || [ $REPLY == "Q" ]; then
                echo "Are you sure? [Y/N]"
                read -rsn1
                if [ $REPLY == "y" ] || [ $REPLY == "Y" ]; then
                        kill -- -$$
                        exit
                fi
        fi
        echo ""
        sleep 1
done

# Wait
wait

When I'm sudo'ing, if I press CTRL+C, or press "Q" to quit, it will exit the parent (main) process but not the children and I receive this error:

adam@TG-BBCAM-01:~ $ sudo ./temp.sh
Press 'Q' to quit
Are you sure? [Y/N]
./temp.sh: line 31: kill: (-29098) - No such process
./temp.sh: line 1: kill: (-29098) - No such process
adam@TG-BBCAM-01:~ $ SOME PROCESS RUNNING IN THE BACKGROUND
SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES
ANOTHER ONE...
SOME PROCESS RUNNING IN THE BACKGROUND
SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES
ANOTHER ONE...
SOME PROCESS RUNNING IN THE BACKGROUND
SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES
ANOTHER ONE...
SOME PROCESS RUNNING IN THE BACKGROUND

Obviously because it didn't kill the children, they're still running and flooding my shell still with output. When I don't sudo, it works great.

It seems to be the kill -- -$$ in both the trap and the "keypress monitor" part of my script. Commenting one out doesn't fix the other one.

Does anyone know how I can fix this? I would just like it to work in most any situation (well at least, sudo or not).

Thanks!

1 Answer 1

2

It's kill -- -"$pgid", that is it has to be a process group id. kill -- -"$$" would only work if the shell was the process group leader which it's not when running with sudo from an interactive shell:

$ sudo bash -c 'ps -j; exit'
  PID  PGID   SID TTY          TIME CMD
26786 26786 29719 pts/39   00:00:00 sudo
26794 26786 29719 pts/39   00:00:00 bash
26795 26786 29719 pts/39   00:00:00 ps

sudo is the process group leader, not bash.

So, you'd need to do kill -- -"$(ps -o pgid= -p "$$")" or simply:

kill 0

Which is the command to kill your own process group.

In any case, that's only a valid thing to do if your script is called on its own from an interactive shell (that performs job control).

Also note that in:

(the-script; echo "$?")

Or:

the-script | cmd

The subshell in the first case or cmd is the second are also placed in that same process group so would be killed as well by that kill 0.

1
  • If my shell's PID is less than 5 digits long, ps will left-pad it with spaces. A more robust solution would be [...] -o pgid:1= [...], which will set the column width to 1 character and remove the extra whitespace.
    – SliceThePi
    Oct 22, 2019 at 23:24

You must log in to answer this question.

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