If you have long running batch processes with PHP that are run by cron and you want to ensure there’s only ever one running copy of the script, you can use the functions getmypid() and posix_kill() to check to see if you already have a copy of the process running. This post has a PHP class for checking if the script is already running.
Each process running on a Linux/Unix computer has a pid, or process identifier. In PHP this can be retrieved using getmypid() which will return an integer number. This pid number can be saved to a file and each time the script is run a check made to see if the file exists. If it is the posix_kill() function can be used to see if a process is running with that pid number.
My PHP class for doing this is below. Please feel free to use this and modify to suit your individual requirements.
class pid { protected $filename; public $already_running = false; function __construct($directory) { $this->filename = $directory . '/' . basename($_SERVER['PHP_SELF']) . '.pid'; if(is_writable($this->filename) || is_writable($directory)) { if(file_exists($this->filename)) { $pid = (int)trim(file_get_contents($this->filename)); if(posix_kill($pid, 0)) { $this->already_running = true; } } } else { die("Cannot write to pid file '$this->filename'. Program execution halted.n"); } if(!$this->already_running) { $pid = getmypid(); file_put_contents($this->filename, $pid); } } public function __destruct() { if(!$this->already_running && file_exists($this->filename) && is_writeable($this->filename)) { unlink($this->filename); } } }
and it can be used as follows:
$pid = new pid('/tmp'); if($pid->already_running) { echo "Already running.n"; exit; } else { echo "Running...n"; }
To test it, you could add "sleep(30);" to the end of the test script above, run the script and then run the script again. The second time you run it the script will output "Already running" and exit.
The class tidies up the pid file at the end of the script run automatically in the desctructor, so all you need to do is create the object at the start and then check to see if it’s already running.
Update 29 Oct 2008: I forgot to mention when I wrote this yesterday that posix_kill() will return true if there is already a process running with $pid which is being run by the same user your script is running as. Pid numbers do get recycled when the limit is reached, so it is potentially possible (although unlikely) that you might be checking another process that was run by you and not the same exact PHP script. If you run the script as root querying any pid that is actually running will return true.