Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a cronjob which runs php on a wordpres cron.php file. Its mainly used to schedule post and i believe it may refresh cache. Anyways...

I run the cron job every minute. I checked out the ps often and i see TWO php instance running cron.php. Now this is unnecessary because running one instance will do everything it needs to. I have another job which checks for ram and sometimes two instance trip it off (i expect a high amount of ram available at all times, i can lower it but i dont want to). I hardly believe one job can take more than a minute (although it may).

How do i run a job but not if the process exist already? I don't think the php code itself can check unless it connects/uses the db? Is there a cron command i may use? I don't want to kill an instance if its >1minute. Just not spawn new ones.

share|improve this question
add comment

3 Answers

Make your crontab entry run this:

if mv /var/run/my-php-job.pending /var/run/my-php-job.running 2>/dev/null; then
  echo $$ >|/var/run/my-php-job.running   # optional
  … # run the job
  : >|/var/run/my-php-job.running         # optional
  mv /var/run/my-php-job.running /var/run/my-php-job.pending
fi

Put this in an @reboot crontab entry:

rm -f /var/run/my-php-job.running
touch /var/run/my-php-job.pending

The name of the file serves as a lock. While it's .running, there's a running job and the next job won't start. When it's .pending, the running job starts and switches to .running.

If you include the optional lines, the process ID of the shell will be written to the .running file, for investigation purposes if a job gets stuck. A log file would make this mostly redundant.

If the shell running the job crashes (which is unlikely, and only risks happening if someone deliberately kills it or in a low memory condition, the lock file will get stuck on .running. (If the job itself crashes, that's no problem.) You can detect the sudden death of a prior script, but it's significantly harder.

share|improve this answer
add comment

Here is a simple bash script solution; you probably can do the same in the cron.php script. It actually checks for processes that run too long; for an automated system, this is probably a good idea.

#!/bin/bash

# Exit if process is already running
if test -e /tmp/wordpress-job.pid; then
  # Check if the pid that was stored in /tmp/wordpress-job.pid does exist
  if ps ax -o pid= | grep $(cat /tmp/wordpress-job.pid ) &> /dev/null; then
    exit 0
  fi
fi

# Create the file that marks this process as running
echo $$ > /tmp/wordpress-job.pid

# Some extra security check to prevent the pid file
# to survive.
trap "rm -f /tmp/wordpress-job.pid" EXIT TERM INT HUP 

# Start the long-running process in the background
sleep 3600 & # long-running process

# Sleep some time before trying to kill that process
sleep 300

# Kill job if it takes longer than it should
kill %1

# Delete the file that marks this process as running
rm -f /tmp/wordpress-job.pid

You have to replace the "sleep 3600" with your php command line, and change the 300 below to the maximum time your script should be allowed to run.

share|improve this answer
2  
I believe there is a race condition if another process creates the /tmp/wordpress-job.pid in between the test and the echo. A safer way would be to create a /tmp/wordpress-job.$$ file, and then attempt to create a hard link to /tmp/wordpress-job.pid - the link will fail if /tmp/wordpress-job.pid already exists, and it's atomic. –  Paul Tomblin Apr 2 '12 at 17:45
    
I don't think that's necessary. After all, the process is only launched once per minute. But the script could of course be changed, to be on the safe side. –  daniel kullmann Apr 2 '12 at 19:49
add comment

There are special utilities for avoiding parallel runs: flock in util-linux, lockf in BSD systems, shlock in NetBSD and with INN and cnews packages.

With most likely case (Linux) call something similar to:

flock -w 60 /somedir/lockfile cron.php

Recipes in other answers are home-grown flock alternatives and are useful only in case of absense of such tool.

OTOH you can deal with such lock in your program directly, but you should repeat all details carefully, otherwise you can create race condition.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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