1

I have the following script; it is supposed to start a process if it is not running:

$ cat keepalive_stackexchange_sample.bash
#!/bin/bash -xv

# This script checks if a process is running and starts it if it's not.
# If the process is already running, the script exits with exit code 0.
# If the process was restarted by the script, the script exits with exit code 0.
# If the process fails to start, the script exits with exit code 2.
# If the first argument is "-h" or "--help", the script prints a help message and exits with exit code 10.
#


if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
  echo "Usage: $0 process_name"
  echo "This script checks if a process is running and starts it if it's not."
  exit 10
fi

if [[ -z "$1" ]]; then
  echo "Error: No process name provided."
  echo "Usage: $0 process_name"
  exit 12
fi

if pgrep -x -f $@ > /dev/null; then
  echo "Process '$@' is already running."
  exit 0
else
  echo "Process '$@' is not running. Starting it..."
  if ! "$@" &> /dev/null; then
    echo "Error: Failed to start process '$@'"
    exit 2
  fi
  echo "Process '$@' started successfully"
  exit 0
fi

This script works fine if it the process name it gets has only one word, for instance keepalive_stackexchange_sample.bash sox_authfiles_auditd_v2r.

However, if the process I'm checking has arguments, pgrep thinks these arguments are meant for it, and the script does not work as expected, for instance, if I have running:

$ ps -ef | grep [s]ox_ | grep v2r
username   12150     1  0 23:07 ?        00:00:00 sox_user_auditd_v2r -c
$

and I run keepalive_stackexchange_sample.bash sox_user_auditd_v2r -c, I'll get the following error:

+ pgrep -x -f sox_user_auditd_v2r -c
pgrep: invalid option -- 'c'
Usage: pgrep [-flvx] [-d DELIM] [-n|-o] [-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]
        [-u EUIDLIST] [-U UIDLIST] [-G GIDLIST] [-t TERMLIST] [PATTERN]
+ echo 'Process '\''sox_user_auditd_v2r' '-c'\'' is not running. Starting it...'

and the script will run sox_user_auditd_v2r -c even though it is already running.

Any suggestion how can I have the script work on processes with arguments?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
boardrider
  • 252
  • 1
  • 12
  • 2
    You can try `--` to signify the end of options - see for example [What does "--" (double-dash) mean?](https://unix.stackexchange.com/questions/11376/what-does-double-dash-mean) however I suspect you will then get an error about passing more than one pattern to pgrep - you'll likely need to pass a single *quoted* string and use `pgrep -x -f -- "$1"`, or perhaps change `$@` to `"$*"` – steeldriver Feb 14 '23 at 23:42
  • Thanks, @steeldriver, but I cannot seem to find the right way to make `pgrep` to do what I want. See https://unix.stackexchange.com/questions/735653/how-to-use-pgrep-from-a-script-when-the-checked-process-includes-a-c-that – boardrider Feb 15 '23 at 18:34

1 Answers1

0

You need to quote the process name & options so that pgrep sees it as a single string.

You can either do that when running the script:

keepalive_stackexchange_sample.bash 'sox_user_auditd_v2r -c'

or in the script itself:

if pgrep -x -f "$*" > /dev/null; then ...

This is one of the few times when you want to use "$*" rather than "$@" because you want all of your script's args to become one string for pgrep rather than separate words - pgrep takes exactly one pattern argument.

Later in the script, when you re-start the process, you should use "$@" because you need to have the command and all its options as arguments treated as separate words by the shell.

cas
  • 1
  • 7
  • 119
  • 185