According to the man page of pidof
which I missed (thank @cas for remind me):
-o omitpid
Tells pidof to omit processes with that process id. The
special pid %PPID can be used to name the parent process
of the pidof program, in other words the calling shell or
shell script.
So -o %PPID
mean ignore the current running script, just retrieve PID of another instance of the script (if any).
The original code can be rewrite without mixture of backticks and $() for command substitution:
#!/bin/bash
ensure only one instance of script is running
if pidof -x $(basename $0) -o %PPID > /dev/null
then
exit
fi
UPDATE: As @Alfe pointed out: "Using pidof
based on basename $0
in any case is an insecure way to perform this check. Two very different programs can have the same basename...". Here is another solution based on @Alfe comment using pid-file:
#!/usr/bin/env bash
set -e
pid_file="fixed_name.pid"
ensure only one instance of script is running
if [ -f "$pid_file" ] && ps -p $(cat "$pid_file") > /dev/null
then
# another instance of this script is running
exit
fi
write script's PID to pid-file
printf "$$" > "$pid_file"
do some work
I can see one problem in this solution as there can be a valid PID assigned to a different program in a stale PID file. Of course, no solution is perfect. But this gone too far from my original question.
pidof
based onbasename $0
in any case is an insecure way to perform this check. Two very different programs can have the same basename, after all. So if another program with the same basename is already running, your program will (wrongly) assume that it is already running and thus not start. It is better to have your script check a pid-file upon startup: Read a pid from a file with a fixed name. Check if the process of this pid is running. If not, write your own pid into this file and run; otherwise stop. – Alfe Nov 22 '21 at 15:54