I'm writing a bash script that spawns a couple of child processes, and will be run by a cron
job every hour. It's actually running an rsync
command to a remote server, and the associated ssh
connection.
If the rsync command or script takes too long I'd like to kill it and its child processes, but give it a grace period first. The script runs every hour, but the next 2 attempts will see that a previous instance of the script is running and exit before trying to commence a transfer. The third subsequent attempt will kill the original, still running instance, before starting a new transfer.
I've decided to control this by writing to a PID file, first instance writes its PID to the file, the next two attempts write their PID to the file before exiting. The third attempt kills the first one, then overwrites the PID file with the new PID. Any successful completion wipes the PID file. To kill all children I've decided to use the PGID of the original script instance which I get with:
previous_pid=$(head -n1 "$pid_file")
previous_groupid=$(ps -hp "$previous_pid" -o pgid:1)
Then kill it with:
kill -- -"$previous_pid"
My concern is that there may be a condition where the original script has somehow died without cleaning up the PID file, and that PID is being reused also reusing the PGID, so I'll end up killing a completely unrelated process. How can I avoid this?