当前位置: 首页 > news >正文

php:代码中怎么搭建一个类似linux系统的crontab服务

一、前言

        最近使用自己搭建的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:{impersonationLevel=impersonate}!\\\\' . $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
ficrontabl=`crontab -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

相关文章:

php:代码中怎么搭建一个类似linux系统的crontab服务

一、前言 最近使用自己搭建的php框架写一些东西&#xff0c;需要用到异步脚本任务的执行&#xff0c;但是是因为自己搭建的框架没有现成的机制&#xff0c;所以想自己搭建一个类似linux系统的crontab服务的功能。 因为如果直接使用linux crontab的服务配置起来很麻烦&#xff0…...

【LeetCode: 958. 二叉树的完全性检验 + bfs + 二叉树】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…...

MinDoc 安装与部署

下载可执行文件 mindoc mindoc_linux_amd64.zip 上传并解压压缩包 cd /opt mkdir mindoc cd mindocunzip mindoc_linux_amd64.zip 创建数据库 CREATE DATABASE mindoc_db DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; 配置数据库 将解压目录下 conf/app.conf.exam…...

从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(基础组件实现)

目录 基础组件实现 如何将图像和文字显示到OLED上 如何绘制图像 如何绘制文字 如何获取字体&#xff1f; 如何正确的访问字体 如何抽象字体 如何绘制字符串 绘制方案 文本绘制 更加方便的绘制 字体附录 ascii 6x8字体 ascii 8 x 16字体 基础组件实现 我们现在离手…...

windows系统如何检查是否开启了mongodb服务

windows系统如何检查是否开启了mongodb服务&#xff01;我们有很多软件开发&#xff0c;网站开发时候需要使用到这个mongodb数据库&#xff0c;下面我们看看&#xff0c;如何在windows系统内排查&#xff0c;是否已经启动了本地服务。 在 Windows 系统上&#xff0c;您可以通过…...

VS安卓仿真器下载失败怎么办?

如果网络不稳定&#xff0c;则VS的安卓仿真器很容易下载失败&#xff0c;如下 Downloaded file <USER_HOME>\AppData\Local\Temp\xamarin-android-sdk\x86_64-35_r08.zip not found for Android SDK archive https://dl.google.com/android/repository/sys-img/google_a…...

计算机网络一点事(24)

TCP可靠传输&#xff0c;流量控制 可靠传输&#xff1a;每字节对应一个序号 累计确认&#xff1a;收到ack则正确接收 返回ack推迟确认&#xff08;不超过0.5s&#xff09; 两种ack&#xff1a;专门确认&#xff08;只有首部无数据&#xff09; 捎带确认&#xff08;带数据…...

视频拼接,拼接时长版本

目录 视频较长&#xff0c;分辨率较大&#xff0c;这个效果很好&#xff0c;不耗用内存 ffmpeg imageio&#xff0c;适合视频较短 视频较长&#xff0c;分辨率较大&#xff0c;这个效果很好&#xff0c;不耗用内存 ffmpeg import subprocess import glob import os from nats…...

制造企业的成本核算

一、生产成本与制造费用的区别 (1)生产成本,是直接用于产品生产,构成产品实体的材料成本。 包括企业在生产经营过程中实际消耗的原材料、辅助材料、备品备件、外购半成品、燃料、动力包装物以及其它直接材料,和直接参加产品生产的工人工资,以及按生产工人的工资总额和规…...

doris:高并发导入优化(Group Commit)

在高频小批量写入场景下&#xff0c;传统的导入方式存在以下问题&#xff1a; 每个导入都会创建一个独立的事务&#xff0c;都需要经过 FE 解析 SQL 和生成执行计划&#xff0c;影响整体性能每个导入都会生成一个新的版本&#xff0c;导致版本数快速增长&#xff0c;增加了后台…...

LLMs之WebRAG:STORM/Co-STORM的简介、安装和使用方法、案例应用之详细攻略

LLMs之WebRAG&#xff1a;STORM/Co-STORM的简介、安装和使用方法、案例应用之详细攻略 目录 STORM系统简介 1、Co-STORM 2、更新新闻 STORM系统安装和使用方法 1、安装 pip安装 直接克隆GitHub仓库 2、模型和数据集 两个数据集 FreshWiki数据集 WildSeek数据集 支持…...

鸿蒙HarmonyOS实战-ArkUI动画(页面转场动画)_鸿蒙arkui tab 切换动画

PageTransitionExit({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number}) 在HarmonyOS中&#xff0c;PageTransitionEnter和PageTransitionExit是用于控制页面切换动画的参数。它们分别表示页面进入和退出时的动画。1. type&#xff08;动画类型…...

图漾相机-ROS2-SDK-Ubuntu版本编译(新版本)

文章目录 前言1.Camport ROS2 SDK 介绍1.1 Camport ROS2 SDK源文件介绍1.2 Camport ROS2 SDK工作流程1.2.1 包含头文件1.2.2 2 初始化 ROS 2 节点1.2.3 创建节点对象1.2.4 创建发布者对象并实现发布逻辑1.2.5 启动 ROS 2 1.3 ROS2 SDK环境配置与编译1.3.1 Ubuntu 20.04 下ROS2 …...

小程序的协同工作与发布

1.小程序API的三大分类 2.小程序管理的概念&#xff0c;以及成员管理两个方面 3.开发者权限说明以及如何维护项目成员 4.小程序版本...

解锁维特比算法:探寻复杂系统的最优解密码

引言 在复杂的技术世界中&#xff0c;维特比算法以其独特的魅力和广泛的应用&#xff0c;成为通信、自然语言处理、生物信息学等领域的关键技术。今天&#xff0c;让我们一同深入探索维特比算法的奥秘。 一、维特比算法的诞生背景 维特比算法由安德鲁・维特比在 1967 年提出…...

计算机网络一点事(20)

IEEE802.11 无线局域网 分类有无基础设施 星型拓扑&#xff0c;基本服务集BSS一基站多移动站&#xff0c;服务集标识符SSID不超过32b&#xff0c;可接入802.3 漫游&#xff1a;移动站从一个基本服务集切换到另一个&#xff08;类似换联WiFi&#xff09; 802.11帧&#xff1…...

java求职学习day23

MySQL 单表 & 约束 & 事务 1. DQL操作单表 1.1 创建数据库,复制表 1) 创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8; 2) 将 db1 数据库中的 emp 表 复制到当前 db2 数据库 1.2 排序 通过 ORDER BY 子句 , 可以将查询出的结果进行排序 ( 排序只…...

Vue-cli 脚手架搭建

安装node.js 官网下载node.js安装包&#xff0c;地址&#xff1a;Node.js — Download Node.js 先在node.js即将要安装的路径下创建两个文件夹&#xff1a;node_cache&#xff08;缓存&#xff09;、node_global&#xff08;全局&#xff09; 点击安装包&#xf…...

认识小程序的基本组成结构

1.基本组成结构 2.页面的组成部分 3.json配置文件 4.app.json文件(全局配置文件&#xff09; 5.project.config.json文件 6.sitemap.json文件 7.页面的.json配置文件 通过window节点可以控制小程序的外观...

Spring Boot 热部署实现指南

在开发 Spring Bot 项目时&#xff0c;热部署功能能够显著提升开发效率&#xff0c;让开发者无需频繁重启服务器就能看到代码修改后的效果。下面为大家详细介绍一种实现 Spring Boot 热部署的方法&#xff0c;同时也欢迎大家补充其他实现形式。 步骤一、开启 IDEA 自动编译功能…...

如果最资深的工程师明天提离职,继任者多久能正常推进工作?

老周走的那天&#xff0c;把电脑交给了公司。密码交了&#xff0c;群退了&#xff0c;交接文档写了几十页。三个月后&#xff0c;团队需要调取三年前的产品数据。翻遍服务器&#xff0c;找到一个叫"老周项目"的文件夹&#xff0c;里面是"最终版""最终…...

从AVR到ARM架构迁移实战:SAMD平台外设编程与性能调优指南

1. 从AVR到ARM&#xff1a;一次架构跃迁的深度解析如果你和我一样&#xff0c;是从Arduino Uno、Nano这类经典的AVR平台一路玩过来的&#xff0c;那么当你第一次拿到一块Adafruit Feather M0或者Arduino Zero时&#xff0c;那种感觉就像是开惯了手动挡的老爷车&#xff0c;突然…...

QRazyBox终极指南:如何快速修复损坏的二维码

QRazyBox终极指南&#xff1a;如何快速修复损坏的二维码 【免费下载链接】qrazybox QR Code Analysis and Recovery Toolkit 项目地址: https://gitcode.com/gh_mirrors/qr/qrazybox QRazyBox是一款专业级的二维码分析与恢复工具包&#xff0c;专为修复损坏的二维码而设…...

别再被EC11编码器波形坑了!STM32F103外部中断驱动避坑指南(附完整代码)

EC11编码器驱动开发实战&#xff1a;从硬件滤波到软件防抖的全方位避坑指南 旋转编码器作为人机交互的重要组件&#xff0c;在嵌入式系统中应用广泛。EC11以其性价比和可靠性成为许多项目的首选&#xff0c;但实际开发中&#xff0c;工程师常被信号抖动、方向误判等问题困扰。本…...

基于RAG架构的本地知识库构建:从原理到Shannon实战

1. 项目概述&#xff1a;一个面向开发者的高效本地知识库构建工具最近在折腾个人知识管理和团队文档沉淀时&#xff0c;发现了一个挺有意思的开源项目&#xff0c;叫Shannon。这项目名挺有深意&#xff0c;取自信息论之父克劳德香农&#xff0c;一听就知道是跟信息处理和知识组…...

Blender 3MF插件:从设计到打印的无缝桥梁 [特殊字符]

Blender 3MF插件&#xff1a;从设计到打印的无缝桥梁 &#x1f680; 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 还在为3D模型在不同软件间转换而烦恼吗&#xff1f;B…...

5G核心网虚拟化部署的功耗优化实践

1. 5G核心网虚拟化部署的功耗挑战在5G网络大规模商用的背景下&#xff0c;核心网(5GC)的虚拟化部署已成为行业主流趋势。与传统的专用硬件设备不同&#xff0c;基于NFV(网络功能虚拟化)的5GC可以运行在商用服务器(COTS)上&#xff0c;这种架构转型带来了显著的灵活性和成本优势…...

冠珠瓷砖×莫氏鸡煲×叠滘东胜东队,德叔有请,莫叔掌勺,“力撑”叠滘龙船传承

5月10日&#xff0c;2026叠滘龙船漂移大赛金牌合作伙伴冠珠瓷砖品牌代表、新明珠集团董事长叶德林“德叔”有请&#xff0c;莫氏鸡煲创始人“莫叔”掌勺&#xff0c;携火爆全网的莫氏祛湿鸡煲、紫洞黄皮酒&#xff0c;探班叠滘东胜东队训练场。当天下午&#xff0c;德叔、莫叔还…...

新人如何快速融入技术团队?这5个细节决定你的第一印象

对于软件测试工程师而言&#xff0c;加入一个新的技术团队&#xff0c;挑战远不止于记住人名和门禁密码。你将面对的是一套陌生的系统架构、一份可能长达数百页的需求文档、一个仍在迭代中的自动化测试框架&#xff0c;以及一群拥有不同技术背景和沟通风格的开发伙伴。在这样的…...

VS Code本地代码评审扩展:结构化JSON存储与AI协同实践

1. 项目概述&#xff1a;一个纯粹本地的代码评审伴侣 如果你和我一样&#xff0c;日常重度依赖 VS Code&#xff0c;并且经常需要处理代码评审任务——无论是和同事异步协作&#xff0c;还是借助 AI 助手&#xff08;如 Claude、GitHub Copilot、Cursor&#xff09;来审查自己…...