4

I have configured my webservers cron jobs to trigger some PHP script, every 15min, but sometimes the script takes more than 15 min to complete execution, by the time another process of the same script starts. which is creating problems in our logic. I want only one instance of the same process running, and if it is completed then only let the other process execute (don't want to put process in a queue, just terminate at that moment and execute at next interval).

Example: I have three PHP file which will be called by the webservers cron job every 15 min. let say a.php, b.php, c.php. the script might take more than 15 min to complete execution. on end of execution it updates our database, hence can't run two copy of same script file (this will break our logic). Like say a.php is triggered at 4.00 pm and at 4.15pm again cron will trigger a.php. here I want to check if a.php has completed execution, if not skip the call and trigger it at 4.30pm by checking the same case, but b.php, c.php and a.php are run parallel (but same instances can't).

3
  • Could you clarify whether you want to skip a job if the previous one is still running or kill it off and start fresh? Your question isn't clear.
    – Caleb
    Commented Jun 10, 2011 at 10:57
  • @caleb the instance of the same process should not run at same time. Commented Jun 10, 2011 at 11:29
  • Tried lockfiles?..
    – alex
    Commented Jun 10, 2011 at 11:46

3 Answers 3

4

The standard practice is to use a pid file. Every time the script executes, have it check a file to see if it's already running somewhere. The order of operations is outlined below.

  • read pid out of /var/run/yourscriptname.pid
  • check if pid is running, exit if it is
  • get your pid, write it to /var/run/yourscriptname.pid
  • execute as normal
  • remove pid file

In your case this will do, but there are some cases where a script might be called fast enough that in the time between checking the pid and writing the pidfile, another process starts up and also sees no pidfile and continues to execute. You can further tighten things by using advisory locking. It is a facility the OS provides on just about every Unix.

References:

1

It is super simple via flock:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job

Credit to this answer. I came here by google, so I thought sharing it here as well.

0

It's hard to tell from your question if you want to start with a new job every time or just skip a rotation if it is still running.

If you want to start fresh each time, the simplest hack is to add a killall your_command; your_command to your cron.

Otherwise try pgrep you_command || your_command in your cron line to only execute if a current one is NOT found running.

You could also get fancier and register the PID's of your job in some kind of run file and then check that run file for active jobs before you start work. If you find one you can either exit and let it run or kill the other one off and mark your own PID as the currently running one.

4
  • i want to skip process if instance of the same script is running. Commented Jun 10, 2011 at 11:14
  • Then use the second option. The pgrep searches for an existing process of a given name and returns true if finds one. Since you want to run your command only if it fails to find one, use the || logical OR operator to run your command if pgrep returns false.
    – Caleb
    Commented Jun 10, 2011 at 11:32
  • i have tried the pgrep but it executes, even if the process is running, i have used the command like pgrep php test.php || echo "already running.." Commented Jun 16, 2011 at 6:51
  • Hah you're problably running into issues recognizing the name of the process because you are calling it from the interpreter. Instead set the hashbang in your script to the right value for your path to php and run it using ./test.php. You should be able to prgrep for that much easier.
    – Caleb
    Commented Jun 16, 2011 at 20:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .