0

I have a shell script executed by cron and I want to control that it's not already running. This is my control test:

set -A processes
ps -elf | grep -v grep | grep -E "/bin/ksh.+scriptName" | while read line ;do processes[${#processes[@]}]="$line";done
if [ ${#processes[@]} -gt 1 ]; then
    for i in {0..$((${#processes[@]}-1))}; do echo "${processes[$i]}"; done
    exit 1
fi

The problem is that this control returns sometimes 2 processes (of itself):

F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD

0 S user 12486 12485 0 85 0 - 2469 - 15:30 ? 00:00:00 /bin/ksh /path/scriptName ARG1

1 D user 12503 12486 0 85 0 - 2469 get_wr 15:30 ? 00:00:00 /bin/ksh /path/scriptName ARG1

I do not understand why it happens sometimes...How to resolve this problem? How to control a script is not already running (without "flag"/semaphore file)? Thanks for your help!

user1334149
  • 161
  • 1
  • 7
  • Your script is broken in quite a number of areas.. (1) nothing fills the `processes` array. (`line` is filled by `read`). (2) you cannot use variable arguments with brace expansion in a for loop (not without bastardizing it). E.g. `{0..$((${#processes[@]}-1))}` does not work. `i` becomes `{0..somenum}` not `0 1 2 3 ... somenum`. You will have better luck with the command `pidof` to locate the process you want to control --or-- have your cron script write its PID out (`$$`) to a temp file and launch a subshell to read the pid and do what you need. Just a few thoughts. – David C. Rankin Aug 13 '14 at 05:58

2 Answers2

0

Two options:

  1. Allow the job to start, but have scriptName script check if it is already running and kill itself.
  2. Switch to a more sophisticated job scheduler such as http://nerds.airbnb.com/introducing-chronos/
Be Kind To New Users
  • 9,672
  • 13
  • 78
  • 125
0

Using pipes can spawn subprocesses, which show up in the process table. Limit the "ps" output and it becomes easier to parse:

ps -eo pid,ppid,args | grep -vw $$ | grep -qE "[0-9]+ /bin/ksh $0" && echo "ALREADY RUNNING"

This removes anything from the list that has the current PID ($$) as its PID or Parent PID, and then matches the scriptname as a pattern. You really don't even need the "[0-9]+" in the pattern, since the first grep excludes all of your child processes (otherwise the "grep" itself would match).