Created
September 18, 2014 11:02
-
-
Save zandzpider/98c434a8dc71dbfc43bf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* https://gist.github.com/andergmartins/5066143 | |
* From: http://abhinavsingh.com/blog/2009/12/how-to-use-locks-in-php-cron-jobs-to-avoid-cron-overlaps/ | |
*/ | |
class CronHelper | |
{ | |
const LOCK_DIR = '/tmp/'; | |
const LOCK_SUFFIX = '.lock'; | |
const LOCK_AGE_MAX = 3600; | |
private $pid = false; | |
private $file = false; | |
private $locked = false; | |
/** | |
* @param string $file optional | |
*/ | |
function __construct($file = '') | |
{ | |
$this->initialize(); | |
global $argv; | |
if (!$file && is_array($argv)) | |
{ | |
$file = implode('.', $argv); | |
} | |
$this->file = self::LOCK_DIR.$file.self::LOCK_SUFFIX; | |
} | |
/** | |
* @return bool | |
*/ | |
public function isRunning() | |
{ | |
if (!$this->pid) | |
{ | |
return false; | |
} | |
$pids = explode(PHP_EOL, `ps -e | awk '{print $1}'`); | |
if (in_array($this->pid, $pids)) | |
{ | |
return true; | |
} | |
} | |
/** | |
* @return bool|int | |
*/ | |
public function lock() | |
{ | |
// unlock needs to be called before a new lock can be done | |
if ($this->locked) | |
{ | |
error_log("==$this->pid== Already locked, please wait..."); | |
return false; | |
} | |
if (file_exists($this->file)) | |
{ | |
$file_age = (time() - filemtime($this->file)); // in seconds | |
// Is running? | |
$this->pid = file_get_contents($this->file); | |
if ($this->isRunning()) | |
{ | |
// check for staled locks | |
if ($file_age > self::LOCK_AGE_MAX) | |
{ | |
error_log("==$this->pid== Lock staled. Killing PID! Age: $file_age / ".self::LOCK_AGE_MAX." (Seconds)"); | |
// kill the running script | |
exec('kill -9 ' .$this->pid); | |
$this->unlock(); | |
return $this->lock(); | |
} | |
error_log("==$this->pid== Already in progress..."); | |
return false; | |
} | |
else | |
{ | |
error_log("==$this->pid== Previous job died abruptly..."); | |
} | |
} | |
$this->pid = getmypid(); | |
file_put_contents($this->file, $this->pid); | |
error_log("==$this->pid== Lock acquired, processing the job..."); | |
$this->locked = true; | |
return $this->pid; | |
} | |
/** | |
* @return bool | |
*/ | |
public function unlock() | |
{ | |
if (file_exists($this->file)) | |
{ | |
unlink($this->file); | |
} | |
if ($this->pid) | |
{ | |
error_log("==$this->pid== Releasing lock..."); | |
$this->pid = false; | |
} | |
$this->locked = false; | |
return true; | |
} | |
/** | |
* @return bool | |
* @throws Exception | |
*/ | |
private function initialize() | |
{ | |
if (!file_exists(self::LOCK_DIR)) | |
{ | |
if (!mkdir(self::LOCK_DIR)) | |
{ | |
throw new Exception(sprintf('Could not create folder LOCK_DIR (%s)', self::LOCK_DIR)); | |
} | |
} | |
if (!is_writable(self::LOCK_DIR)) | |
{ | |
throw new Exception(sprintf('Unable to write to LOCK_DIR (%s)', self::LOCK_DIR)); | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment