4

I have a Python script that I'd like to run from a cronjob and then check every minute to see if it is still running and if not then start it again.

Cronjob is:

/usr/bin/python2.7 /home/mydir/public_html/myotherdir/script.py

there is some info on this but most answers don't really detail the full process clearly, e.g.:

Using cron job to check if python script is running

e.g. in that case, it doesn't state how to run the initial process and record the PID. It leaves me with a lot of questions unfortunately.

Therefore, could anyone give me a simple guide to how to do this?

e.g. full shell script required, what command to start the script, and so on.

Andrew Tobilko
  • 44,067
  • 12
  • 74
  • 128
the_t_test_1
  • 891
  • 1
  • 8
  • 24
  • Possible duplicate of [Run cron job only if it isn't already running](https://stackoverflow.com/questions/2366693/run-cron-job-only-if-it-isnt-already-running) – l'L'l Aug 15 '17 at 23:20
  • I wouldn't run it from cron. I'd create a server process as part of the O/S kickoff scripts (Iinit.d on Linux) and configure it to restart on failure or crash. I haven't done this in over ten years so I'd suggest trying stack exchange serverfault to research this. More of a sys admin question. – LAS Aug 15 '17 at 23:41

3 Answers3

4

There is now a better way to do this via utility called flock, directly from cron task within a single line. flock will acquire a lock before it runs your app and release it after it is run. The format is as follows:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile <your cron job>

For your case, this'd be:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/bin/python2.7 /home/mydir/public_html/myotherdir/script.py

-n tells it to fail immediately if it cannot acquire the lock. There is also -w <seconds> option, it will fail if it cannot acquire the lock within given time frame.

 * * * * /usr/bin/flock -w <seconds> /tmp/fcj.lockfile <your cron job>
Caner
  • 49,709
  • 33
  • 153
  • 169
3

It's not that hard. First set up the crontab to run a checker every minute:

* * * * * /home/mydir/check_and_start_script.sh

Now in /home/mydir/check_and_start_script.sh,

#!/bin/bash
pid_file='/home/mydir/script.pid'
if [ ! -s "$pid_file" ] || ! kill -0 $(cat $pid_file) > /dev/null 2>&1; then
  echo $$ > "$pid_file"
  exec /usr/bin/python2.7 /home/mydir/public_html/myotherdir/script.py
fi

This checks to see if there's a file with the process id of the last run of the script. If it's there, it reads the pid and checks if the process is still running. If not, then it puts the pid of the currently running shell in the file and executes the python script in the same process, terminating the shell. Otherwise it does nothing.

Don't forget to make the script executable

chmod 755 /home/mydir/check_and_start_script.sh
Gene
  • 42,664
  • 4
  • 51
  • 82
1

You should actually take a step back and think what and why you are doing it

Do you need to actually start your long_running program from cron? The reason i ask is that you then write another program(watcher) that starts your long_running program. I hope that you see that yo actually do not need cron to start your long_running program.

So what you have is a watcher firing every minute and starting long_running program if it is not running.

Now you need to actually understand what you are trying to do because there are many ways this can be done. If this is an exercise watcher can call ps and work out from there if it runs and start it. in bash you can do

[ -z "$(ps -ef | grep -v grep | grep myprogname)" ] && { echo runit;  }

you just replace myprogname with the name and run it with command that starts your long_running code on the back ground - perhaps

however you should use another tool. systemd, daemontools or others

Sedy Vlk
  • 535
  • 3
  • 12