3

In our application, we start some background processes. The pid of these processes is saved to a file.

pids values are re-used when the maximum is reached or when the system is rebooted.

How can I reliably check that the process with pid X is still the same process for which X was stored.

I've read https://serverfault.com/questions/366474/whats-a-proper-way-of-checking-if-a-pid-is-running and https://stackoverflow.com/questions/3043978/how-to-check-if-a-process-id-pid-exists but these solutions never check if the process that has pid X is the still same process as the one for which the pid was stored.

I need this info to reliably

  • check the process is still running
  • kill the process without risking to kill a different process that now has pid X

related https://serverfault.com/questions/279178/what-is-the-range-of-a-pid-on-linux-and-solaris

I will post my current solution. I'd like to know if it's a sensible approach and if there are better ways to do this.

carl verbiest
  • 471
  • 4
  • 11
  • This only answers half of your question, but you can check if a process exists and is running with `kill -0 $pid`; e. g. `if kill -0 "$pid"; then printf "PID %d exists and is running.\n" "$pid"`. – DopeGhoti Nov 02 '21 at 17:08
  • It seems you are reinventing service manager, if so, wrapping your background process into a systemd service should be easy and reliable. – AnyDev Nov 03 '21 at 16:21

1 Answers1

0

I created following solution for this

My start script contains

nohup $commandline >> $TEMP/logfile 2>&1 &
MYPID=$!
echo $MYPID > pidfile
cat /proc/$MYPID/cmdline >> pidfile

My stop script reads the pidfile and checks if the cmdline corresponds to the one originally saved

[ -f pidfile ] || { echo no pidfile; exit 1; }
read pid < pidfile
psatstart=$(tail -1 pidfile)
psnow=$(</proc/$pid/cmdline)

if [[ "$psnow" == "$psatstart" ]]
then
    echo kill $pid
    kill $pid || { echo kill $pid failed; exit 2; }
    while ps -p $pid
    do
        sleep 1
    done
else
    echo pid $pid not the same, assume already ended
    echo S $psatstart
    echo N $psnow
fi
rm pidfile
carl verbiest
  • 471
  • 4
  • 11
  • Why `cat /proc/$MYPID/cmdline >> pidfile` instead of `printf '%s\n' "$commandline" >> pidfile`? You already have the command line after all. – terdon Nov 02 '21 at 18:01
  • @terdon /proc/$MYPID/cmdline is not equal to $commandline, e.g. spaces are replaced by \0 . – carl verbiest Nov 03 '21 at 14:02
  • Precisely, and this breaks the approach since even if you were to fix the wrong `psnow=$(/proc/$pid/cmdline)`, and change it to `psnow=$(cat /proc/$pid/cmdline)` which is presumably what you want, it will lose the `\0` since `\0` cannot be stored in shell variables. So, since you already _have_ the command line stored in a variable, why not use that directly and avoid the problem? – terdon Nov 03 '21 at 14:07