From c5f0af8e438a6c4b8c8e07423e6140630eb8c191 Mon Sep 17 00:00:00 2001 From: Exodus4D Date: Tue, 29 Dec 2015 00:47:45 +0100 Subject: [PATCH] Updated cron.php --- app/cron.ini | 2 +- app/lib/cron.php | 125 +++++++++++++++++------------ app/main/controller/controller.php | 5 -- 3 files changed, 75 insertions(+), 57 deletions(-) diff --git a/app/cron.ini b/app/cron.ini index 06adc52a..af484c23 100644 --- a/app/cron.ini +++ b/app/cron.ini @@ -21,4 +21,4 @@ deactivateMapData = Cron\MapUpdate->deactivateMapData, @hourly deleteMapData = Cron\MapUpdate->deleteMapData, @downtime ; delete character log data -deleteLogData = Cron\CharacterUpdate->deleteLogData, @instant \ No newline at end of file +deleteLogData = Cron\CharacterUpdate->deleteLogData, @hourly \ No newline at end of file diff --git a/app/lib/cron.php b/app/lib/cron.php index 28a619b6..efc68de3 100644 --- a/app/lib/cron.php +++ b/app/lib/cron.php @@ -6,27 +6,33 @@ class Cron extends \Prefab { const E_Undefined='Undefined property: %s::$%s', E_Invalid='"%s" is not a valid name: it should only contain alphanumeric characters', + E_NotFound='Job %s doesn\' exist', + E_Callable='Job %s cannot be called'; + //@} + + //@{ Log message + const L_Execution='%s (%.3F s)'; //@} /** @var bool */ public $log=FALSE; - /** @var bool */ - public $cli=TRUE; - /** @var bool */ public $web=FALSE; - /** @var string */ - public $clipath; + /** @var bool */ + public $silent=TRUE; + + /** @var string Script path */ + public $script='index.php'; + + /** @var string PHP CLI path */ + protected $binary; /** @var array */ protected $jobs=array(); - /** @var bool */ - protected $async=FALSE; - /** @var array */ protected $presets=array( 'yearly'=>'0 0 1 1 *', @@ -37,6 +43,20 @@ class Cron extends \Prefab { 'hourly'=>'0 * * * *', ); + /** + * Set binary path after checking that it can be executed and is CLI + * @param string $path + * @return string + */ + function binary($path) { + if (function_exists('exec')) { + exec($path.' -v 2>&1',$out,$ret); + if ($ret==0 && preg_match('/cli/',@$out[0],$out)) + $this->binary=$path; + } + return $this->binary; + } + /** * Schedule a job * @param string $job @@ -67,7 +87,6 @@ class Cron extends \Prefab { function isDue($job,$time) { if (!isset($this->jobs[$job]) || !$parts=$this->parseExpr($this->jobs[$job][1])) return FALSE; - foreach($this->parseTimestamp($time) as $i=>$k) if (!in_array($k,$parts[$i])) return FALSE; @@ -78,51 +97,50 @@ class Cron extends \Prefab { * Execute a job * @param string $job * @param bool $async + * @return bool TRUE = job has been executed / FALSE = job has been delegated to a background process */ function execute($job,$async=TRUE) { if (!isset($this->jobs[$job])) - return; + user_error(sprintf(self::E_NotFound,$job),E_USER_ERROR); $f3=\Base::instance(); - if (is_string($func=$this->jobs[$job][0])){ + if (is_string($func=$this->jobs[$job][0])) $func=$f3->grab($func); - } - if (!is_callable($func)) - return; - if ($async && $this->async) { + user_error(sprintf(self::E_Callable,$job),E_USER_ERROR); + if ($async && isset($this->binary)) { // PHP docs: If a program is started with this function, in order for it to continue running in the background, // the output of the program must be redirected to a file or another output stream. // Failing to do so will cause PHP to hang until the execution of the program ends. - $dir=''; - $file='index.php'; - if ($this->clipath) { - $dir=dirname($this->clipath); - $file=basename($this->clipath); - } + $dir=dirname($this->script); + $file=basename($this->script); if (@$dir[0]!='/') $dir=getcwd().'/'.$dir; - exec(sprintf('cd "%s";php %s /cron/%s > /dev/null 2>/dev/null &',$dir,$file,$job)); - } else { - $start=microtime(TRUE); - call_user_func_array($func,array($f3)); - if ($this->log) { - $log=new Log('cron.log'); - $log->write(sprintf(self::L_Execution,$job,microtime(TRUE)-$start)); - } + exec(sprintf('cd "%s";%s %s /cron/%s > /dev/null 2>/dev/null &',$dir,$this->binary,$file,$job)); + return FALSE; } + $start=microtime(TRUE); + call_user_func_array($func,array($f3)); + if ($this->log) { + $log=new Log('cron.log'); + $log->write(sprintf(self::L_Execution,$job,microtime(TRUE)-$start)); + } + return TRUE; } /** * Run scheduler, i.e executes all due jobs at a given time * @param int $time * @param bool $async + * @return array List of executed jobs */ function run($time=NULL,$async=TRUE) { if (!isset($time)) $time=time(); + $exec=array(); foreach(array_keys($this->jobs) as $job) if ($this->isDue($job,$time)) - $this->execute($job,$async); + $exec[$job]=$this->execute($job,$async); + return $exec; } /** @@ -131,16 +149,18 @@ class Cron extends \Prefab { * @param array $params */ function route($f3,$params) { - - if (PHP_SAPI=='cli'?!$this->cli:!$this->web) + if (PHP_SAPI!='cli' && !$this->web) $f3->error(404); - if (isset($params['job'])) - $this->execute($params['job'],FALSE); - else{ - // IMPORTANT! async does not work on Windows - // -> my development environment is Windows :(( - $async = FALSE; - $this->run(NULL, $async); + $exec=isset($params['job'])? + array($params['job']=>$this->execute($params['job'],FALSE)): + $this->run(); + if (!$this->silent) { + if (PHP_SAPI!='cli') + header('Content-Type: text/plain'); + if (!$exec) + die('Nothing to do'); + foreach($exec as $job=>$ok) + echo sprintf('%s [%s]',$job,$ok?'OK':'async')."\r\n"; } } @@ -195,8 +215,10 @@ class Cron extends \Prefab { //! Read-only public properties function __get($name) { - if (in_array($name,array('jobs','async','presets'))) + if (in_array($name,array('binary','jobs','presets'))) return $this->$name; + if ($name=='clipath') // alias for script [deprecated] + return $this->script; trigger_error(sprintf(self::E_Undefined,__CLASS__,$name)); } @@ -204,13 +226,13 @@ class Cron extends \Prefab { function __construct() { $f3=\Base::instance(); $config=(array)$f3->get('CRON'); - - foreach(array('log','cli','web') as $k) - if (isset($config[$k])) - $this->$k=(bool)$config[$k]; - foreach(array('clipath') as $k) - if (isset($config[$k])) - $this->$k=(string)$config[$k]; + foreach(array('log','web','script','silent') as $k) + if (isset($config[$k])) { + settype($config[$k],gettype($this->$k)); + $this->$k=$config[$k]; + } + if (isset($config['binary'])) + $this->binary($config['binary']); if (isset($config['jobs'])) foreach($config['jobs'] as $job=>$arr) { $handler=array_shift($arr); @@ -219,10 +241,11 @@ class Cron extends \Prefab { if (isset($config['presets'])) foreach($config['presets'] as $name=>$expr) $this->preset($name,is_array($expr)?implode(',',$expr):$expr); - if (function_exists('exec') && exec('php -r "echo 1+3;"')=='4') - $this->async=TRUE; - if ($this->cli || $this->web) - $f3->route(array('GET /cron','GET /cron/@job'),array($this,'route')); + if (!isset($this->binary)) + foreach(array('php','php-cli') as $path) // try to guess the binary name + if ($this->binary($path)) + break; + $f3->route(array('GET /cron','GET /cron/@job'),array($this,'route')); } } \ No newline at end of file diff --git a/app/main/controller/controller.php b/app/main/controller/controller.php index eca80c2f..ea0671ea 100644 --- a/app/main/controller/controller.php +++ b/app/main/controller/controller.php @@ -379,11 +379,6 @@ class Controller { }else{ // render error in template $f3->set('errorData', [$error]); - - // show Errors in Dev environment - if( !self::isProduction() ){ - var_dump($error); - } } }