| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- <?php
- /**
- * The model file of cron module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
- * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Yidong Wang <yidong@cnezsoft.com>
- * @package cron
- * @version $Id$
- * @link https://www.zentao.net
- */
- class cronModel extends model
- {
- /**
- * 通过ID获取定时任务。
- * Get by Id.
- *
- * @param int $cronID
- * @access public
- * @return object
- */
- public function getById($cronID)
- {
- return $this->dao->select('*')->from(TABLE_CRON)->where('id')->eq($cronID)->fetch();
- }
- /**
- * Get crons.
- *
- * @param string $params
- * @access public
- * @return array
- */
- public function getCrons($params = '')
- {
- return $this->dao->select('*')->from(TABLE_CRON)
- ->where('1=1')
- ->beginIF(strpos($params, 'nostop') !== false)->andWhere('status')->ne('stop')->fi()
- ->beginIF($this->config->edition != 'max')
- ->andWhere('command')->ne('moduleName=measurement&methodName=initCrontabQueue')
- ->andWhere('command')->ne('moduleName=measurement&methodName=execCrontabQueue')
- ->fi()
- ->fetchAll('id', false);
- }
- /**
- * Parse crons.
- *
- * @param array $crons
- * @access public
- * @return array
- */
- public function parseCron($crons)
- {
- $this->app->loadClass('crontab', true);
- $parsedCrons = array();
- foreach($crons as $cron)
- {
- $row = "{$cron->m} {$cron->h} {$cron->dom} {$cron->mon} {$cron->dow} {$cron->command}";
- preg_match_all('/(\S+\s+){5}|.*/', $row, $matches);
- if($matches[0])
- {
- try
- {
- $runTime = isset($cron->datetime) ? $cron->datetime : date(DT_DATETIME1);
- $parsedCron = array();
- $parsedCron['schema'] = trim($matches[0][0]);
- $parsedCron['command'] = trim($matches[0][1]);
- $parsedCron['cron'] = crontab::factory($parsedCron['schema']);
- $parsedCron['time'] = $parsedCron['cron']->getNextRunDate($runTime);
- $parsedCrons[$cron->id] = $parsedCron;
- }
- catch(InvalidArgumentException $e)
- {
- $this->dao->update(TABLE_CRON)->set('status')->eq('stop')->where('id')->eq($cron->id)->exec();
- continue;
- }
- }
- }
- $this->dao->update(TABLE_CRON)->set('lastTime')->eq(date(DT_DATETIME1))->where('`lastTime` IS NULL')->andWhere('status')->ne('stop')->exec();
- return $parsedCrons;
- }
- /**
- * 修改定时任务状态。
- * Change cron status.
- *
- * @param int $cronID
- * @param string $status
- * @param bool $changeTime
- * @access public
- * @return bool
- */
- public function changeStatus($cronID, $status, $changeTime = false)
- {
- $data = new stdclass();
- $data->status = $status;
- if($status == 'running' or $changeTime) $data->lastTime = date(DT_DATETIME1);
- $this->dao->update(TABLE_CRON)->data($data)->where('id')->eq($cronID)->exec();
- return dao::isError() ? false : true;
- }
- /**
- * 记录定时任务日志。
- * Log cron.
- *
- * @param string $log
- * @param bool $isDebugMode
- * @access public
- * @return void
- */
- public function logCron($log, $isDebugMode = false)
- {
- if($isDebugMode && !$this->config->debug) return false;
- if(!is_writable($this->app->getLogRoot())) return false;
- $runMode = PHP_SAPI == 'cli' ? '_cli' : '';
- $file = $this->app->getLogRoot() . "cron$runMode." . date('Ymd') . '.log.php';
- if(!is_file($file)) $log = "<?php\n die();\n" . $log;
- $fp = fopen($file, "a");
- fwrite($fp, $log);
- fclose($fp);
- }
- /**
- * 获取定时任务最后执行时间。
- * Get last executed time.
- *
- * @access public
- * @return string
- */
- public function getLastTime()
- {
- return zget(zget($this->config->cron, 'scheduler', array()), 'lastTime', '');
- }
- /**
- * 检查定时任务是否还在工作。
- * Runnable cron.
- *
- * @access public
- * @return bool
- */
- public function runnable()
- {
- if(empty($this->config->global->cron)) return false;
- $lastTime = $this->getLastTime();
- if(helper::isZeroDate($lastTime) or ((time() - strtotime($lastTime)) > $this->config->cron->maxRunTime)) return true;
- return false;
- }
- /**
- * 检查定时任务是否已修改。
- * Check change cron.
- *
- * @access public
- * @return bool
- */
- public function checkChange()
- {
- $updatedCron = $this->dao->select('*')->from(TABLE_CRON)->where('`lastTime` IS NULL')->andWhere('status')->ne('stop')->fetch();
- return $updatedCron ? true : false;
- }
- /**
- * 创建定时任务。
- * Create cron.
- *
- * @access public
- * @return int
- */
- public function create()
- {
- $cron = fixer::input('post')
- ->add('status', 'normal')
- ->skipSpecial('m,h,dom,mon,dow,command')
- ->get();
- if(!$this->config->features->cronSystemCall and $cron->type == 'system')
- {
- dao::$errors[] = $this->lang->cron->notice->errorType;
- return false;
- }
- $result = $this->checkRule($cron);
- if(!empty($result))
- {
- dao::$errors = $result;
- return false;
- }
- $this->dao->insert(TABLE_CRON)->data($cron)->autoCheck()->exec();
- return $this->dao->lastInsertID();
- }
- /**
- * 修改定时任务。
- * Update cron.
- *
- * @param int $cronID
- * @access public
- * @return bool
- */
- public function update($cronID)
- {
- $cron = fixer::input('post')
- ->add('lastTime', NULL)
- ->skipSpecial('m,h,dom,mon,dow,command')
- ->get();
- if(!$this->config->features->cronSystemCall and $cron->type == 'system')
- {
- dao::$errors[] = $this->lang->cron->notice->errorType;
- return false;
- }
- $result = $this->checkRule($cron);
- if(!empty($result))
- {
- dao::$errors = $result;
- return false;
- }
- $this->dao->update(TABLE_CRON)->data($cron)->autoCheck()->where('id')->eq($cronID)->exec();
- return dao::isError() ? false : true;
- }
- /**
- * 检查定时任务是否符合规则。
- * Check cron rule.
- *
- * @param object $cron
- * @access public
- * @return array
- */
- public function checkRule($cron)
- {
- if($cron->m === '' || $cron->m[0] == '-' || preg_match('/[^0-9\*\-\/,]/', $cron->m)) return array('m' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->m));
- if($cron->h === '' || $cron->h[0] == '-' || preg_match('/[^0-9\*\-\/,]/', $cron->h)) return array('h' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->h));
- if($cron->dom === '' || $cron->dom[0] == '-' || preg_match('/[^0-9\*\-\/,\?LWC]/', $cron->dom))return array('dom' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->dom));
- if($cron->mon === '' || $cron->mon[0] == '-' || preg_match('/[^0-9\*\-\/,]/', $cron->mon)) return array('mon' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->mon));
- if($cron->dow === '' || $cron->dow[0] == '-' || preg_match('/[^0-9\*\-\/,\?LC#]/', $cron->dow))return array('dow' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->dow));
- if(is_numeric($cron->m) && ($cron->m < 0 || $cron->m > 59)) return array('m' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->m));
- if(is_numeric($cron->h) && ($cron->h < 0 || $cron->h > 23)) return array('h' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->h));
- if(is_numeric($cron->dom) && ($cron->dom < 1 || $cron->dom > 31)) return array('dom' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->dom));
- if(is_numeric($cron->mon) && ($cron->mon < 1 || $cron->mon > 12)) return array('mon' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->mon));
- if(is_numeric($cron->dow) && ($cron->dow < 0 || $cron->dow > 6)) return array('dow' => sprintf($this->lang->cron->notice->errorRule, $this->lang->cron->dow));
- if(empty($cron->command)) return array('command' => sprintf($this->lang->error->notempty, $this->lang->cron->command));
- return array();
- }
- /**
- * 重启cron,更新scheduler的execId。
- * Restart cron.
- *
- * @access public
- * @return void
- */
- public function restartCron($execId)
- {
- $this->dao->update(TABLE_CONFIG)->set('value')->eq($execId)
- ->where('owner')->eq('system')
- ->andWhere('module')->eq('cron')
- ->andWhere('section')->eq('scheduler')
- ->andWhere('`key`')->eq('execId')
- ->exec();
- $this->dao->delete()->from(TABLE_QUEUE)->where('createdDate')->le(date("Y-m-d H:i:s", strtotime("-1 week")))->exec();
- $this->logCron(date('G:i:s') . " restart\n\n");
- }
- /**
- * 更新定时任务的最后执行时间。
- * Update last time of cron.
- *
- * @param string $role
- * @param int $execId
- * @access public
- * @return void
- */
- public function updateTime($role, $execId)
- {
- $now = date(DT_DATETIME1);
- $settings = $this->dao->select('*')->from(TABLE_CONFIG)->where('owner')->eq('system')->andWhere('module')->eq('cron')->andWhere('section')->eq($role)->fetchAll('key', false);
- if($role == 'scheduler')
- {
- if(isset($settings['execId']))
- {
- $setting = $settings['execId'];
- if($setting->value != strval($execId)) $this->dao->update(TABLE_CONFIG)->set('value')->eq($execId)->where('id')->eq($setting->id)->exec();
- }
- else
- {
- $data = new stdclass();
- $data->owner = 'system';
- $data->module = 'cron';
- $data->section = 'scheduler';
- $data->key = 'execId';
- $data->value = $execId;
- $this->dao->insert(TABLE_CONFIG)->data($data)->exec();
- }
- if(isset($settings['lastTime']))
- {
- $setting = $settings['lastTime'];
- $this->dao->update(TABLE_CONFIG)->set('value')->eq($now)->where('id')->eq($setting->id)->exec();
- }
- else
- {
- $data = new stdclass();
- $data->owner = 'system';
- $data->module = 'cron';
- $data->section = 'scheduler';
- $data->key = 'lastTime';
- $data->value = $now;
- $this->dao->insert(TABLE_CONFIG)->data($data)->exec();
- }
- }
- else
- {
- if(isset($settings[strval($execId)]))
- {
- $setting = $settings[strval($execId)];
- $this->dao->update(TABLE_CONFIG)->set('value')->eq($now)->where('id')->eq($setting->id)->exec();
- }
- else
- {
- $data = new stdclass();
- $data->owner = 'system';
- $data->module = 'cron';
- $data->section = 'consumer';
- $data->key = $execId;
- $data->value = $now;
- $this->dao->insert(TABLE_CONFIG)->data($data)->exec();
- }
- }
- }
- }
|