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?

  • 1
    Why not add a cron job to have them run every {second,minute, hour} etc., instead of having the cron job restart them? – eyoung100 Sep 30 '14 at 15:22
  • sounds like a good idea and I'd be completely open to that Idea, can you provide me some idea of how to implement that and will accept as answer – Javacadabra Sep 30 '14 at 15:24
  • 1
    I'm working on a more detailed answer merging davidanns with an explanation, but the explaining takes a while., ie teach a man to fish... – eyoung100 Sep 30 '14 at 15:38
  • @eyoung100 thank you very much, waiting with anticipation! – Javacadabra Sep 30 '14 at 15:40
  • 1
    Done!!! Finally – eyoung100 Sep 30 '14 at 15:54
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

* * * * * lockfile -r 0 /tmp/the.lock && php get_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

  • amazing answer, thank you very much for that! – Javacadabra Sep 30 '14 at 15:55
  • 2
    Shouldn't the command be: 'lockfile -r 0 /tmp/the.lock && (php parse_tweets.php; rm -f /tmp/the.lock)'? – Andy May 15 '15 at 21:44
  • Yes it should. Will not work otherwise. – Dima Stefantsov Jun 5 '17 at 6:46
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.