131 lines
4.4 KiB
PHP
131 lines
4.4 KiB
PHP
|
<?php
|
|||
|
|
|||
|
namespace addons\crontab\library;
|
|||
|
|
|||
|
use fast\Http;
|
|||
|
use think\Config;
|
|||
|
use think\Db;
|
|||
|
|
|||
|
class CommandRunnable implements \Jenner\SimpleFork\Runnable
|
|||
|
{
|
|||
|
protected $connect = null;
|
|||
|
protected $crontab = null;
|
|||
|
|
|||
|
public function __construct($crontab)
|
|||
|
{
|
|||
|
$this->crontab = $crontab;
|
|||
|
}
|
|||
|
|
|||
|
public function run()
|
|||
|
{
|
|||
|
$processId = getmypid();
|
|||
|
|
|||
|
//这里需要强制重连数据库,使用已有的连接会报2014错误
|
|||
|
$this->connect = Db::connect([], true);
|
|||
|
$this->connect->execute("SELECT 1");
|
|||
|
|
|||
|
$message = '';
|
|||
|
$result = false;
|
|||
|
$this->crontabLog = null;
|
|||
|
$log = [
|
|||
|
'crontab_id' => $this->crontab['id'],
|
|||
|
'executetime' => time(),
|
|||
|
'completetime' => null,
|
|||
|
'content' => '',
|
|||
|
'processid' => $processId,
|
|||
|
'status' => 'inprogress',
|
|||
|
];
|
|||
|
$this->connect->name("crontab_log")->insert($log);
|
|||
|
$this->crontabLogId = $this->connect->getLastInsID();
|
|||
|
try {
|
|||
|
if ($this->crontab['type'] == 'url') {
|
|||
|
if (substr($this->crontab['content'], 0, 1) == "/") {
|
|||
|
// 本地项目URL
|
|||
|
$message = shell_exec('php ' . ROOT_PATH . 'public/index.php ' . $this->crontab['content']);
|
|||
|
$result = (bool)$message;
|
|||
|
} else {
|
|||
|
$arr = explode(" ", $this->crontab['content']);
|
|||
|
$url = $arr[0];
|
|||
|
$params = $arr[1] ?? '';
|
|||
|
$method = $arr[2] ?? 'POST';
|
|||
|
try {
|
|||
|
// 远程异步调用URL
|
|||
|
$ret = Http::sendRequest($url, $params, $method);
|
|||
|
$result = $ret['ret'];
|
|||
|
$message = $ret['msg'];
|
|||
|
} catch (\Exception $e) {
|
|||
|
$message = $e->getMessage();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} elseif ($this->crontab['type'] == 'sql') {
|
|||
|
$ret = $this->sql($this->crontab['content']);
|
|||
|
$result = $ret['ret'];
|
|||
|
$message = $ret['msg'];
|
|||
|
} elseif ($this->crontab['type'] == 'shell') {
|
|||
|
// 执行Shell
|
|||
|
$message = shell_exec($this->crontab['content']);
|
|||
|
$result = !is_null($message);
|
|||
|
}
|
|||
|
} catch (\Exception $e) {
|
|||
|
$message = $e->getMessage();
|
|||
|
}
|
|||
|
|
|||
|
//设定任务完成
|
|||
|
$this->connect->name("crontab_log")->where('id', $this->crontabLogId)->update(['content' => $message, 'completetime' => time(), 'status' => $result ? 'success' : 'failure']);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 执行SQL语句
|
|||
|
*/
|
|||
|
protected function sql($sql)
|
|||
|
{
|
|||
|
|
|||
|
// 执行SQL
|
|||
|
$sqlquery = str_replace('__PREFIX__', config('database.prefix'), $sql);
|
|||
|
$sqls = preg_split("/;[ \t]{0,}\n/i", $sqlquery);
|
|||
|
|
|||
|
$result = false;
|
|||
|
$message = '';
|
|||
|
$this->connect->startTrans();
|
|||
|
try {
|
|||
|
foreach ($sqls as $key => $val) {
|
|||
|
if (trim($val) == '' || substr($val, 0, 2) == '--' || substr($val, 0, 2) == '/*') {
|
|||
|
continue;
|
|||
|
}
|
|||
|
$message .= "\nSQL:{$val}\n";
|
|||
|
$val = rtrim($val, ';');
|
|||
|
if (preg_match("/^(select|explain)(.*)/i ", $val)) {
|
|||
|
$count = $this->connect->execute($val);
|
|||
|
if ($count > 0) {
|
|||
|
$resultlist = Db::query($val);
|
|||
|
} else {
|
|||
|
$resultlist = [];
|
|||
|
}
|
|||
|
|
|||
|
$message .= "Total:{$count}\n";
|
|||
|
$j = 1;
|
|||
|
foreach ($resultlist as $m => $n) {
|
|||
|
$message .= "\n";
|
|||
|
$message .= "Row:{$j}\n";
|
|||
|
foreach ($n as $k => $v) {
|
|||
|
$message .= "{$k}:{$v}\n";
|
|||
|
}
|
|||
|
$j++;
|
|||
|
}
|
|||
|
} else {
|
|||
|
$count = $this->connect->getPdo()->exec($val);
|
|||
|
$message = "Affected rows:{$count}";
|
|||
|
}
|
|||
|
}
|
|||
|
$this->connect->commit();
|
|||
|
$result = true;
|
|||
|
} catch (\PDOException $e) {
|
|||
|
$message = $e->getMessage();
|
|||
|
$this->connect->rollback();
|
|||
|
$result = false;
|
|||
|
}
|
|||
|
return ['ret' => $result, 'msg' => $message];
|
|||
|
}
|
|||
|
}
|