4

I am wondering if someone might point me in the right direction. I've got little experience working with the Linux command line and recently due to various factors in work I've been required to gain knowledge.

Basically I have two php scripts that reside in a directory on my server. For the purposes of the application these scripts must be running continuously. Currently I implement that this way:

nohup sh -c 'while true; do php get_tweets.php; done' >/dev/null &

and

nohup sh -c 'while true; do php parse_tweets.php; done' >/dev/null &

However, I've noticed that despite the infinte loop the scripts to stop periodically and I'm forced to restart them. I'm not sure why but they do. That has made me look into the prospect of a CRON job that checks if they are running and if they are not, run them/restart them.

Would anyone be able to provide me with some information on how to go about this?

3 Answers3

7

I'd like to expand on Davidann's answer since you are new to the concept of a cron job. Every UNIX or Linux system has a crontab stored somewhere. The crontab is a plain text file. Consider the following: (From the Gentoo Wiki on Cron)

#Mins  Hours  Days   Months  Day of the week
10     3      1      1       *       /bin/echo "I don't really like cron"
30     16     *      1,2     *       /bin/echo "I like cron a little"
*      *      *      1-12/2  *       /bin/echo "I really like cron"

This crontab should echo "I really like cron" every minute of every hour of every day every other month. Obviously you would only do that if you really liked cron. The crontab will also echo "I like cron a little" at 16:30 every day in January and February. It will also echo "I don't really like cron" at 3:10 on the January 1st.

Being new to cron, you probably want to comment the starred columns so that you know what each column is used for. Every Cron implementation that I know of has always been this order. Now merging Davidann's answer with my commented file:

#Mins  Hours  Days   Months  Day of week
  *     *      *      *       *   lockfile -r 0 /tmp/the.lock && php parse_tweets.php; rm -f /tmp/the.lock


Putting no value in each column defaults to:
Every Minute Of Every Hour Of Every Day Of Every Month All Week Long, --> Every Minute All Year Long.

As Davidann states using a lockfile ensures that only one copy of the php interpreter runs, php parse_tweets.php is the command to "run" the file, and the last bit of the line will delete the lock file to get ready for the next run. I don't like deleting a file every minute, but if this is the behavior you need, this is very acceptable. Writing and Rewriting to disk is just personal preference

eyoung100
  • 6,252
  • 23
  • 53
4

Instead of having a separate cron just to kick it off if it isn't running, why not just use the cron exclusively?

E.g.:

* * * * * 'lockfile -r 0 /tmp/the.lock && (php parse_tweets.php; rm -f /tmp/the.lock)'

This will run the cron job which will execute parse_tweets.php once per minute using a lockfile so that you will only have one copy run by cron running at a time. (It won't keep you from running php parse_tweets.php outside of cron though)

0

Checking at regular intervals is neither convenient nor reliable. If your scripts stop, they won't be restarted until the cron job runs again.

There are tools for ensuring that a process is always running, such as supervise from daemontools, monit, god, supervisord, etc. Start the monitoring tool at boot time and leave it alone.

while true; do … done is a crude but effective monitoring tool, but you need to take a few precautions. nohup is a start. Make sure to redirect standard input so that it isn't the terminal (some implementations of nohup do that for you). You should log the output to a file, and check that file in case of errors.

nohup sh -c 'while true; do …; done' </dev/null >myscript.log 2>&1 &

Also make sure that your shell won't send a signal to that job when it exits. If your shell has a disown builtin, run it.

On many systems, you can arrange for supervisor to start at boot time by registering an @reboot entry. Check the crontab(5) man page on your system to see if @reboot is supported.

@reboot while true; do …; done </dev/null >myscript.log 2>&1