介绍国外的网站有什么不同,wordpress查询标签,网站建设企业蛋糕,可以做翻译兼职的网站有哪些一、前言 最近使用自己搭建的php框架写一些东西#xff0c;需要用到异步脚本任务的执行#xff0c;但是是因为自己搭建的框架没有现成的机制#xff0c;所以想自己搭建一个类似linux系统的crontab服务的功能。 因为如果直接使用linux crontab的服务配置起来很麻烦#xff0…一、前言 最近使用自己搭建的php框架写一些东西需要用到异步脚本任务的执行但是是因为自己搭建的框架没有现成的机制所以想自己搭建一个类似linux系统的crontab服务的功能。 因为如果直接使用linux crontab的服务配置起来很麻烦如果不了解的人接手也不知道你配置了crontab后续拆分生产和测试环境也会很复杂不能一套代码包含所有。 二、配置文件 先在相关配置目录下放一个配置文件例如config/crontab.ini里面配置如下结构其中需要注意的是request_uri参数这个参数是各自框架中使用命令行形式执行任务的命令可以根据自己的框架进行修改。
例我目前的框架执行命令形式是
php index.php request_uri/cli_Test/test ;【使用说明】
;1、检测机制每分钟自动检测一次该配置
;
;2、参数说明
;request_uri为执行任务的命令行
;time控制启动时间分别为分、时、日、月、周
;proc_total运行脚本的进程数
;ip_limit服务器ip限制多个ip英文,分隔[test]
request_uri /cli_Test/test
time 0 3 * * *
proc_total 1
;ip_limit 10.235.62.241
注 time配置方式是一比一复制的linux crontab配置 proc_total支持多个进程执行任务的方式比如队列消费要启用多个进程消费就很方便并且会自动检测执行任务的进程是否存在存在不会重复启动。 ip_limit有时候集群服务器太多但是你只想单台机器执行可以使用该配置限制执行的服务器ip是什么也可以配置多个。 三、监控相关类 1、配置读取类可以解析上述配置文件结构
?php
/*** 配置信息读取类** package Comm*/
class Config {private static $_config array();/*** 读取配置信息** param string $path 节点路径第一个是文件名使用点号分隔。如:app,app.product.test* return array|string*/public static function get($path) {if(!isset(self::$_config[$path])) {$arr explode(., $path);try {$conf parse_ini_file(APP_PATH . config/.$arr[0]..ini, true);} catch (Exception $e) {}if (!empty($conf)) {if (isset($arr[1]) !isset($conf[$arr[1]])) {throw new Exception(读取的配置信息不存在path: . $path); }if (isset($arr[1])) $conf $conf[$arr[1]];if (isset($arr[2]) !isset($conf[$arr[2]])) {throw new Exception(读取的配置信息不存在path: . $path); }if (isset($arr[2])) $conf $conf[$arr[2]];}if (!isset($conf) || is_null($conf)) {throw new Exception(读取的配置信息不存在path: . $path); }self::$_config[$path] $conf;}return self::$_config[$path];}
}2、任务监控类
注其中需要注意的是shell方法的内容如果自己的框架不适用这种执行命令方式可以更改为自己框架的命令。
?php
namespace app\controllers\Cli;/*** Crontab监控* * 注切勿轻易修改*/
class MonitorController
{/*** 检查计划任务*/public function index() {$appEnv \Context::param(APP_ENV);//获取运行环境$appEnvParam !empty($appEnv) ? APP_ENV.$appEnv : ;echo \033[35mCheck Crontab:\r\n\033[0m;$config $this-getConfig();foreach ($config as $key $value) {if (!$this-checkTime(time(), $value[time])) {echo {$key}:[IGNORE]\r\n;continue;}$ip_limit isset($value[ip_limit]) ? explode(,,$value[ip_limit]) : false;for ($i 1; $i $value[proc_total]; $i) {$request_uri {$value[request_uri]}?proc_total{$value[proc_total]}proc_num{$i}{$appEnvParam};//检查进程是否存在$shell $this-shell($request_uri);$num $this-shell_proc_num($shell);echo {$key}_{$i}:;if ($num 1) { //进程已存在echo \033[33m[RUNING]\033[0m;} else { //进程不存在操作if($ip_limit){if(in_array(\Util::getServerIp(),$ip_limit)){echo \033[32m[OK]\033[0m;$this-shell_cmd($request_uri);}else{echo \033[32m[IP LIMIT]\033[0m;}}else{echo \033[32m[OK]\033[0m;$this-shell_cmd($request_uri);}}echo \r\n;}}}/*** 获取crontab配置* * return array*/public function getConfig() {return \Config::get(crontab);}/*** 检查是否该执行crontab了* * param int $curr_datetime 当前时间* param string $timeStr 时间配置* return boolean*/protected function checkTime($curr_datetime, $timeStr) {$time explode( , $timeStr);if (count($time) ! 5) {return false;}$month date(n, $curr_datetime); // 没有前导0$day date(j, $curr_datetime); // 没有前导0$hour date(G, $curr_datetime);$minute (int)date(i, $curr_datetime);$week date(w, $curr_datetime); // w 0~6, 0:sunday 6:saturdayif ($this-isAllow($week, $time[4], 7, 0) $this-isAllow($month, $time[3], 12) $this-isAllow($day, $time[2], 31, 1) $this-isAllow($hour, $time[1], 24) $this-isAllow($minute, $time[0], 60)) {return true;}return false;}/*** 检查是否允许执行* * param mixed $needle 数值* param mixed $str 要检查的数据* param int $TotalCounts 单位内最大数* param int $start 单位开始值默认为0* return type*/protected function isAllow($needle, $str, $TotalCounts, $start 0) {if (strpos($str, ,) ! false) {$weekArray explode(,, $str);if (in_array($needle, $weekArray))return true;return false;}$array explode(/, $str);$end $start $TotalCounts - 1;if (isset($array[1])) {if ($array[1] $TotalCounts)return false;$tmps explode(-, $array[0]);if (isset($tmps[1])) {if ($tmps[0] 0 || $end $tmps[1])return false;$start $tmps[0];$end $tmps[1];} else {if ($tmps[0] ! *)return false;}if (0 (($needle - $start) % $array[1]))return true;return false;}$tmps explode(-, $array[0]);if (isset($tmps[1])) {if ($tmps[0] 0 || $end $tmps[1])return false;if ($needle $tmps[0] $needle $tmps[1])return true;return false;} else {if ($tmps[0] * || $tmps[0] $needle)return true;return false;}}/*** 执行Shell命令** param string $request_uri*/public function shell_cmd($request_uri) {if (IS_WIN) {$cmd $this-shell($request_uri);pclose(popen(start /B . $cmd, r));}else{$cmd $this-shell($request_uri) . /dev/null ;$pp popen($cmd, r);pclose($pp);}}/*** 获取Shell执行命令** param string $request_uri* return string*/public function shell($request_uri) {return PHP_BIN . . rtrim(APP_PATH, /) . /index.php request_uri\{$request_uri}\;}/*** 检查指定shell命令进程数** param string $shell shell命令* return int*/public function shell_proc_num($shell) {if (IS_WIN) {// Windows 环境下的逻辑if (!extension_loaded(com_dotnet)) {die(COM extension is not installed or loaded.);}$num 0;$shell str_replace([ , \\], [, /], $shell);$computer .;$obj new \COM(winmgmts:{impersonationLevelimpersonate}!\\\\ . $computer . \\root\\cimv2);$processes $obj-ExecQuery(SELECT * FROM Win32_Process);foreach ($processes as $process) {$line str_replace([ , \\], [, /], $process-CommandLine);if (strpos($line, $shell) ! false) {$num;}}return $num;} else {$shell str_replace(array(-, ), array(\-, ), $shell);// $shell preg_quote($shell);$shell str_replace(\?, ?, $shell);$cmd ps -ef | grep -v grep |grep \{$shell}\| wc -l;$pp popen($cmd, r);$num trim(fread($pp, 512)) 0;pclose($pp);return $num;}}
}四、执行初始化脚本
1、init.sh这个脚本主要是把监控任务类的执行方式写入到了linux中的crontab服务后续就不用管了。
2、后续想要增加执行的任务可以直接在crontab.ini中增加即可。
#开启crond
/sbin/service crond start#追加写入crontab监控
phpBin$1
projectPath$2
appEnv$3
if [[ $phpBin || $projectPath ]]; thenecho 请先输入【php bin路径】和【项目根目录路径】exit
fiif [[ $appEnv ! pro $appEnv ! dev ]]; thenecho 请输入环境变量参数:pro生产环境 或 dev测试环境exit
fiif [[ ! -e $phpBin ]]; thenecho 【php bin路径】不正确可尝试使用which php来获取bin路径exit
fiif [[ ! -e $projectPath/index.php ]]; thenecho 【项目根目录路径】不正确exit
ficrontablcrontab -l | grep $phpBin | grep $projectPath | grep request_uri | grep cli_monitor
if [ -z $crontabl ]; thenecho * * * * * $phpBin $projectPath/index.php request_uri/cli_monitor?APP_ENV$appEnv /var/spool/cron/rootecho -e cli_monitor write \033[32m[SUCCESS]\033[0m
elseecho -e cli_monitor already exist \033[32m[SUCCESS]\033[0m
fi