Reputation: 2664
I have seen a PHP code that uses shell commands to determinate if this process is running now, but I've lost it. Can you give me a hint how to do this?
The idea is to create a php file and run this file as a cron job using php -f. The execution time of the script may be 10 seconds, but it also may be 10 minutes. I need to make this cron run once every minute and if the cron from the prevous minute is still running - to stop the new one and let the other one finish.
I'm not very good in shell programming so I need some help.
P.S The idea is to create a daemon without putting an endless PHP process in background.
Upvotes: 3
Views: 1127
Reputation: 1091
The exclusive file lock approach is better than the 'check if file exists' one because if the script crashes before you delete the file, then the lock will still be in place.
Here is the code for file lock:
//Allow only one instance
$fileHandler = fopen('file_lock.lock', 'w');
$hasLock = flock($fileHandler, LOCK_EX | LOCK_NB);
if (!$hasLock)
die("Another instance is already running");
//do work
//release lock
flock($fileHandler, LOCK_UN);
fclose($fileHandler);
The release lock block is optional because the system will automatically release the lock after the script execution.
Upvotes: 2
Reputation: 12644
for many purposes, the following code is ok (there may be a race condition, but for a minutely cronjob this is probably very rare):
if (file_exists($lockfilename)) {
... // lock is already taken
} else {
if ( !file_put_contents($lockfilename, $lockstring)) {
error("unable to write $lockfilename");
}
$lock_taken = true;
... // do what you have to do
if ( !unlink($lockfilename)) {
warning("unable to unlink $lockfilename");
}
$lock_taken = false;
}
The global variable $lock_taken
may be useful to make sure that the lockfile is removed whenever execution is halted. The $lockstring
could be a date or a Unix timestamp, which may be useful for removing the lock if it is clearly too old (but filemtime()
could be enough).
If you absolutely cannot risk the race condition, you have to do something like
if ( !($lockfile = fopen($lockfilename, "x"))) {
... // lock is already taken
} else {
$lock_taken = true;
... // write something to lockfile (optional)
fclose($lockfile);
... // do what you have to do
if ( !unlink($lockfilename)) {
warning("unable to unlink $lockfilename");
}
$lock_taken = false;
}
This only works for local lockfiles, though.
Upvotes: 2
Reputation: 43218
You should try to acquire an exclusive non-blocking lock on a lock file. If you succeed, your process is the only running instance and you should keep the lock until you terminate. If you do not succeed to acquire the lock, then there is already another running instance and you should terminate.
Upvotes: 3