因为要做简单的中控 在实现心跳包的时候遇到了困难 正常的心跳包思路是这样的 举个例子 我写一个登陆签到脚本 当我登陆成功的时候 会把登陆成功这个状态传递给网络上的中控端 当我签到完成的时候会把签到成功的脚本状态传递给网络上的中控端 这样 我们在中控那边就可以清晰的看到当前脚本运行到哪个部分 如果脚本停止 以安卓按键为准会触发一个 OnScriptExit 事件 我们只需要在这个事件里面写上代码 当触发这个事件的时候 我们就给中控端发送下脚本状态为close 或者stop的状态信息 中控端就可以清楚脚本当前具体是处于什么状态 但是这个只是理想化状态 因为 有的时候脚本未必是正常关闭的 这样会导致 在中控端 因为迟迟收不到脚本的最新消息 当前脚本状态无法变化 看起来还在运行 但是实际上已经脚本崩溃导致问题,后来想到了心跳包 就是多开1个线程 间隔一会就向中控端发送信息 来让中控端知道 我这个脚本还在运行 如果超出一定时间内 中控端再也没接收到这个脚本的心跳包 那么中控端就会判定该脚本已经关闭
要解决的问题:从实际上来说 我们中控端有一个额外的操作 就是 间隔一定的时间 就搜索下数据库里面 所有的脚本记录 看看每个记录的最新记录时间和当前时间 相差多少 如果相差太多 就直接让这个记录对应的脚本状态设置了close或者stop 保证应对脚本异常关闭的情况 这也是这个文章的主要要解决的问题
思路:因为是虚拟主机 不是真正的主机 如果是真正的主机 那么可以考虑的办法相当的多 也无需像我这样费尽心机 比如可以用主机系统的计划任务来定时执行某些数据库操作 也可以用mysql的超级管理员的一些功能来实现定时任务 。百度了下 获得了一些基本思路 这些思路无非就是使用 ignore_user_abort(); //函数设置与客户机断开是否会终止脚本 set_time_limit(0); 实现一个无限死循环 在这个死循环里面 我们可以通过sleep进行适当的延迟间隔 来进行一定的操作 但是当我实际的来写代码的时候发现一些原来没有考虑过的问题
产生的新问题:
1.我们访问一次这个特殊页面就开启一个无限死循环(定时任务) 如果开启多个 那么对整个服务器的资源消耗是巨大的 非常影响网站的正常访问 所以我们必须要采取措施让这个无限死循环(定时任务)只能存在1个
2 我们需要有一个开关来控制这个无限循环 开启无限循环(定时任务)我们可以访问特殊页面开启 但是 关闭这个无限循环(定时任务) 我们也需要1个开关来控制 ----->用一个txt的内容来控制关闭
3.我们访问这个特殊页面后就开启了无限死循环(定时任务) 我们可以关闭这个特殊页面 但是这个无限死循环会一直执行下去 我们不清楚这个无限死循环(定时任务)都在干什么 都在忙什么 就算无限死循环(定时任务)出了问题 我们也不清楚 –-->专门做了一个简单的定时任务日志来监控 这个无限循环(定时任务)的运行情况
网页文件结构
browse_log.php 是日志文件 专门用来记录当天的定时任务的运行反馈
timed_task.php 是主文件 只要访问这个网页 就可以开启一个无限死循环(定时任务)
timed_task_18-08-22.log这个其实是真正的日志文件 browse_log.php是读取它的内容到网页上显示而已 但是 每一天都对应一个独立的log文件 log文件名字会变化 所以索性就显示到网页上
timed_task_config.txt 是无限循环(定时任务) 的配置文件 主要是用来关闭所有的无限循环(定时任务)和避免开启多个无限循环(定时任务)
用法:
开启无限循环(定时任务) :确保timed_task_config.txt 存在 并且内容为空 访问timed_task.php 等待页面反馈 如果页面进入卡住状态 则直接查看browse_log.php 看看日志里面是否记录启动成功
关闭无限循环(定时任务) :将timed_task_config.txt的内容改为close 然后等待一会 查看browse_log.php 看看日志里面是否记录关闭 记录了关闭才算关闭成功
日志查看:查看browse_log.php 有一点很关键注意看上下2个正常日志的时间间隔是否是符合你的要求 如果出现一些误差比较大的时间差 那么可以考虑是不是多开了无限循环 可以全部关闭重开下
主文件timed_task,php的代码
<?php ignore_user_abort(); //函数设置与客户机断开是否会终止脚本的执行 set_time_limit(0); // 来设置一个脚本的执行时间为无限长 date_default_timezone_set(‘PRC‘); // 切换到中国的时间 $interval=20;//间隔多久执行一次 $timed_task_config_path="timed_task_config.txt";//负责让这个无限循环停止的一个开关 其实是控制定时任务机制的一个配置文件 如果该文件不存在或者 里面的内容为close 那么定时任务不会执行 如果为open 则会开启一个无限循环来进行监控和执行定时任务 ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>定时任务</title> </head> <body> <?php //问题1 如何控制这些无限循环让他们停止 //问题2 如何避免打开多个无限循环增加服务器的资源消耗 //问题3 无限循环的日志监控和避免无限增加的处理办法 //控制用txt //php定时计划任务 //检测定时任务的配置文件 是否存在或者里面的内容 //strpos($str1,"open") if(file_exists($timed_task_config_path)) { //存在配置文件 开始检测里面的内容 $str1=""; $str1=trim(file_get_contents($timed_task_config_path)); if (is_numeric(strpos($str1,"open"))) { ////1.内容为open 表示当前已经有定时任务线程在运行了 就不再额外执行定时任务 send_timed_task_log("已经有一个定时任务进程存在 不能开启其他的进程"); exit("已经有一个定时任务进程存在 不能开启其他的进程"); } elseif (is_numeric(strpos($str1,"close"))) { ////2.内容为close表示要求定时任务关闭 更不用 send_timed_task_log("配置文件要求关闭所有定时任务进程"); exit("配置文件要求关闭所有定时任务进程"); } else { ////3.如果不是open 和close 那么就锁定该文件然后修改里面的内容为open 修改成功 $fp = fopen($timed_task_config_path, ‘w+‘); if(!is_writable($timed_task_config_path)){ send_timed_task_log("无法写入配置文件 请刷新重试"); exit("<p>无法写入配置文件 请刷新重试</p>"); } flock($fp, LOCK_EX); fwrite($fp, ‘open‘); sleep(1); flock($fp, LOCK_UN); fclose($fp); //////////如果再次读取下配置文件内容判断是否写入成功 成功则开始执行后面的无限循环 不成功提示并结束网页 $str1=""; $str1=trim(file_get_contents($timed_task_config_path)); // echo "<p>".$str1." </p>"; // echo "<p>".strpos($str1,"open")." </p>"; // exit(); if (is_numeric(strpos($str1,"open"))) { ///////////////修改成功 获取到了定时任务进程的权利 send_timed_task_log("启动成功 请关闭网页"); do{ $body=""; if (file_exists($timed_task_config_path)) { $body = trim(file_get_contents($timed_task_config_path)); if (is_numeric(strpos($body,"close"))) { send_timed_task_log("配置文件要求关闭所有的定时任务"); exit("<p>配置文件要求关闭所有的定时任务</p>"); } } else { send_timed_task_log("没有找到定时任务配置文件"); exit("<p>没有找到定时任务配置文件 进程结束</p>"); } //-----------------------定时操作开头------------------------------- send_timed_task_log("<常规检测:一切正常>"); //-----------------------定时操作结尾------------------------------- sleep(rand($interval-2,$interval+2)); // 函数延迟代码执行若干秒 为了避免完全一样 随机下间隔避免一些问题 }while(true); }else{ send_timed_task_log("没有获取到定时任务进程的权限 请刷新重试"); exit("没有获取到定时任务进程的权限 请刷新重试"); } } }else{ send_timed_task_log("定时任务配置文件不存在 不执行该"); exit("<p>定时任务配置文件不存在 不执行该任务</p>"); } //用来发送定时任务日志的函数 function send_timed_task_log($str) { //接收从脚本传递来的日志信息 判断当前的日期 把这个日志信息存储到当前日期命名的日志文件里 if (trim($str)<>""){ $nowtimefilepath="timed_task_".date("y-m-d",time()).".log"; $send_str=date("y-m-d",time()); $send_str=date("Y-m-d H:i:s",time())."----".trim($str)."\r\n"; file_put_contents($nowtimefilepath,$send_str,FILE_APPEND);//????? ??????? }else{ } } ?> </body> </html>
完整下载地址:
https://pan.baidu.com/s/1__xp1oSVdT2aDXj5BjxYHw
原文地址:https://www.cnblogs.com/zjl8455482/p/9521194.html