Run cron job only if it is not already running

So, I'm trying to configure cron to work as a kind of watchdog timer for the daemon I created. If the daemon is dismounted and fails, I want the cron job to restart it periodically ... I'm not sure how possible it is, but I read a couple of cron tutorials and could not find anything that could do what I am looking for. ..

My daemon is launched from a shell script, so I'm really looking for a way to run a cron job ONLY if the previous run of this job is not already running.

I found this post that provided a solution for what I'm trying to do using lock files, and I'm not sure if there is a better way to do this ...

Thanks for your help.

+114
linux bash cron watchdog
Mar 02 '10 at 20:57
source share
15 answers

I do this for the print spooler program I wrote, this is just a shell script:

#!/bin/sh if ps -ef | grep -v grep | grep doctype.php ; then exit 0 else /home/user/bin/doctype.php >> /home/user/bin/spooler.log & #mailing program /home/user/bin/simplemail.php "Print spooler was not running... Restarted." exit 0 fi 

It works every two minutes and is quite effective. I have an email with special information if, for some reason, the process is not running.

+110
Mar 02 '10 at 21:00
source share

Use flock . This is new. It is better.

Now you do not need to write code yourself. Here you can find additional reasons: https://serverfault.com/a/82863

 /usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script 
+98
Oct 29 '15 at 13:51 on
source share

As others have stated, writing and checking a PID file is a good solution. Here is my bash implementation:

 #!/bin/bash mkdir -p "$HOME/tmp" PIDFILE="$HOME/tmp/myprogram.pid" if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -opid= | grep -P "^\s*$(cat ${PIDFILE})$" &> /dev/null); then echo "Already running." exit 99 fi /path/to/myprogram > $HOME/tmp/myprogram.log & echo $! > "${PIDFILE}" chmod 644 "${PIDFILE}" 
+58
Sep 17 2018-11-11T00:
source share

Do not try to do this through cron. Have cron run the script no matter what, and then let the script decide if the program is running and run it if necessary (note that you can use Ruby or Python or your favorite scripting language for this)

+22
Mar 02 '10 at 20:59
source share

Surprisingly, no one mentioned run-one . I solved the problem with this.

  apt-get install run-one 

then add run-one before your crontab script

 */20 * * * * * run-one python /script/to/run/awesome.py 

Check this answer askubuntu SE. You can also find a link to detailed information.

+21
Aug 09 '16 at 1:00
source share

You can also do this as a single line directly in your crontab:

 * * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command> 
+10
Aug 14 2018-12-12T00:
source share

In response to Earlz's answer, you will need a script wrapper that creates the $ PID.running file at startup and deletes it when finished. The wrapper script calls the script you want to run. A wrapper is needed if the target script fails or errors, the pid file is deleted ..

+5
Mar 02
source share

The way I do this when I run php scripts:

Crontab:

 * * * * * php /path/to/php/script.php & 

Php code:

 <?php if (shell_exec('ps aux | grep ' . __FILE__ . ' | wc -l') > 1) { exit('already running...'); } // do stuff 

This command searches the list of system processes for the current php file name; if it exists, the line counter (wc -l) will be more than one, since the search command itself containing the file name

so if you run php crons add the above code to the top of your php code and it will only run once.

+4
Aug 26 '16 at 6:51
source share

I would recommend using an existing tool, for example monit , it will monitor and automatically restart processes. There is more details here . It should be readily available on most distributions.

+3
Mar 02
source share

With lockrun you do not need to write a wrapper script for your cron job. http://www.unixwiz.net/tools/lockrun.html

+3
Oct. 20 '14 at 17:36
source share

This one never let me down:

one.sh

 LFILE=/tmp/one-`echo "$@" | md5sum | cut -d\ -f1`.pid if [ -e ${LFILE} ] && kill -0 `cat ${LFILE}`; then exit fi trap "rm -f ${LFILE}; exit" INT TERM EXIT echo $$ > ${LFILE} $@ rm -f ${LFILE} 

cron work :

 * * * * * /path/to/one.sh <command> 
+3
09 Oct '16 at 14:02
source share

I would suggest the following as an improvement to rsanden's answer (I would post a comment, but did not have enough reputation ...):

 #!/usr/bin/env bash PIDFILE="$HOME/tmp/myprogram.pid" if [ -e "${PIDFILE}" ] && (ps -p $(cat ${PIDFILE}) > /dev/null); then echo "Already running." exit 99 fi /path/to/myprogram 

This avoids possible false matches (and grepping overhead), and it suppresses output and relies only on ps output status.

+1
Feb 20 '14 at 21:11
source share

A simple custom php is enough to achieve. No need to be confused with shell script.

suggests that you want to run php / home / mypath / example.php if you don't run

Then use the following custom php script to do the same job.

create the following /home/mypath/forever.php

 <?php $cmd = $argv[1]; $grep = "ps -ef | grep '".$cmd."'"; exec($grep,$out); if(count($out)<5){ $cmd .= ' > /dev/null 2>/dev/null &'; exec($cmd,$out); print_r($out); } ?> 

Then in your cron add the following

 * * * * * php /home/mypath/forever.php 'php /home/mypath/example.php' 
+1
Apr 10 '16 at 17:42 on
source share
 # one instance only (works unless your cmd has 'grep' in it) ALREADY_RUNNING_EXIT_STATUS=0 bn=`basename $0` proc=`ps -ef | grep -v grep | grep "$bn" | grep -v " $$ "` [ $? -eq 0 ] && { pid=`echo $proc | awk '{print $2}'` echo "$bn already running with pid $pid" exit $ALREADY_RUNNING_EXIT_STATUS } 
+1
Mar 21 '17 at 13:39 on
source share

Consider using pgrep (if available) rather than ps via grep if you are going to follow this route. Although, personally, I have a lot of mileage from form scripts

 while(1){ call script_that_must_run sleep 5 } 

Although this may fail, and cron work orders are often the best way for basic things. Another alternative.

0
May 05 '13 at 2:28
source share



All Articles