Posts Tagged ‘process’

Single Instance PHP Script

November 12th, 2009

When using php scripts on the command line or in the cron, there are often times that you do not want to allow the same script to run more then once at a the same time.

So a single instance application in php.

Personally I use php scripts like this allot. My cron is filled with all kind of tasks that run from the cron.
From backups to just database cleanup scripts and many other.

But most of those scripts will cause problems when running it multiple times.

This small php class has helped me in allot of cases to prevent just that:

class Process {
    private $strPIDFile;
 
    function __construct($pProcessIdFile) {
        $this->strPIDFile = $pProcessIdFile;
        if(file_exists($this->strPIDFile)) {
            if(!is_writable($this->strPIDFile)) {
                throw new Exception('File Not Writable', 101);
            }
 
            $pid = trim(file_get_contents($this->strPIDFile));
            if(posix_kill($pid, 0)) {
                if($this->is_alive($pid)) {
                    //process is alive
                    throw new Exception('Process Already Running', 100);
                } else {
                    //cleanup
                    unlink($this->strPIDFile);
                }
            }
        } else {
            if(!is_writable(dirname($this->strPIDFile))) {
                throw new Exception('Directory Is Not Writeable', 102);
            }
        }
 
        $id = getmypid();
        file_put_contents($this->strPIDFile, $id);
 
    }
 
    public function __destruct() {
        if(file_exists($this->strPIDFile)) {
            unlink($this->strPIDFile);
        }
    }
 
    private function is_alive($pId){
        exec('ps '.$pId, $ProcessState);
        return(count($ProcessState) >= 2);
    }
}

An example on how to use it:

try {
    $Process = new Process('/tmp/myphpscript.pid');
} catch(Exception $ex) {
    switch($ex->getCode()) {
        case 100:
            echo 'Script already running...';
            return;
        case 101:
            echo 'File Not Writable';
            return;
        case 102:
            echo 'Folder Not Writable';
            return;
    }
}

Many people will say that working with exceptions this way isn’t good practice, it’s easy to modify to your own needs if needed.

Now lets break it in small pieces, well, not that many, the class contains a constructor and deconstructor, nothing more.

First the constructor, it takes the full path to the pid file as a parameter.
This pid file is something used by most applications running on your linux machine.
A couple of checks happen to see if the file and directory are writable, once verified that they are, the fun starts.

If the pid file exists, your php script is already running, that is ‘most of the time’ the case.
The file is left behind if your script crashes, so some extra work is required to make sure the process is still alive or not.
If the process can’t be found, then your php script crashed the last time it ran.

Second, the deconstructor. This does the cleanup when your script finishes. All this does is remove the pid file, meaning it will allow the script to be started again by another process.

That’s it!, nothing more to it.
Copy pasting the class and the small try/catch will make your php script a single instance