4

Code:

if [[ "`pidof -x $(basename $0) -o %PPID`" ]]; then exit; fi

Original source of the code: https://forum.rclone.org/t/continuous-syncing/12377/2

I don't understand how this code inside a bash scrip ensure only one instance of the bash script is running.

I understand the part pidof -x $(basename $0) retrieve the process ID of the script but I don't understand what the part -o %PPID used for.

Question: Do anyone know how the code working?

  • 2
    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, 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

1 Answers1

6

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.