【发布时间】:2023-02-20 20:01:00
【问题描述】:
我需要以下问题的帮助,因为我无法弄清楚为什么会这样。
我有一个 RHEL,其中 crontab 是一个每 5 分钟运行一次的 PHP 脚本。
05,15,25,35,45,55 * * * * /usr/bin/php /path/to/script/MYSCRIPT.php
00,10,20,30,40,50 * * * * /usr/bin/php /path/to/script/MYSCRIPT.php
剧本:
1-收集存储在MySQL中的信息
2-通过graph api,收集收件箱邮件(在O365上)
3-执行一些检查
邮件接收的概念是来自系统的一种“心跳”,所以系统每 1 小时发送一封邮件,我只需要检查它是否到达。
检查(第 3 点)包括:如果邮件在上一封电子邮件后的 1.5 小时内到达,则一切正常,否则它会发送类似“系统 XXX 似乎已关闭”的警报。
由于许多活跃的系统(发送心跳)一天一次或两次被故意禁用,我在 mysql 表中添加了一个停机时间字段,它实际上是一个 json 字符串。例子:
(1- 周一 - 7 周日)
{
"1":{"0":["06:50:00","07:10:00"]},
"2":{"0":["06:50:00","07:10:00"]},
"3":{"0":["06:50:00","07:10:00"]},
"4":{"0":["06:50:00","07:10:00"]},
"5":{"0":["06:50:00","07:10:00"]},
"6":{"0":["06:50:00","07:10:00"]},
"7":{"0":["06:50:00","07:10:00"]}
}
在代码中有一个函数可以检查邮件是否在停机时间范围内到达: param:停机日历,now(datetime),null(第三个参数通常为null)
function is_downtime($cal,$now,$getKey=null){
$dayofweek = $now->format("N");
$to_ret=array();
$hournowint = intval($now->format("His"));
if(array_key_exists($dayofweek, $cal)){
foreach ($cal[$dayofweek] as $key => $value) {
$inthour1 = intval(str_replace(":", "", trim($value[0])));
$inthour2 = intval(str_replace(":", "", trim($value[1])));
if(isBetween($value[0],$value[1],$now->format("H:i:s"))){
if($getKey){return [true,$dayofweek,$key];}
return true;
}
}
}
if($getKey){return [false,-1,-1];}
return false;
}
函数是介于:
function isBetween($from, $till, $input) {
$f = DateTime::createFromFormat('!H:i:s', $from);
$t = DateTime::createFromFormat('!H:i:s', $till);
$i = DateTime::createFromFormat('!H:i:s', $input);
if ($f > $t) $t->modify('+1 day');
return ($f <= $i && $i <= $t) || ($f <= $i->modify('+1 day') && $i <= $t);
}
我可以向你保证这很好用。每 5 分钟通过以下调用调用此函数:
...
if(is_downtime(json_decode($conf["down_calendar"],true),$dtnow)){
//do stuff
}else{
//do other stuff
}
...
但有时,当我传递一个日历和一个显然不是停机时间范围的日期时间时,它无论如何都会进入一个真实的案例。
例子:
$snow 显然是一个明确的新日期时间,日历和以前一样
$dtnow=new Datetime();
$calendar='{"1":{"0":["06:50:00","07:10:00"]},"2":{"0":["06:50:00","07:10:00"]},"3":{"0":["06:50:00","07:10:00"]},"4":{"0":["06:50:00","07:10:00"]},"5":{"0":["06:50:00","07:10:00"]},"6":{"0":["06:50:00","07:10:00"]},"7":{"0":["06:50:00","07:10:00"]}}'
如果我将此参数传递给“isDowntime”函数并且 now = friday 16:33,该函数说它是真的(显然是错误的)。 为了获得证据,我添加了一些写入文件的日志代码:
$log->write("DBG - conf=".json_encode($conf));
$log->write("DBG - dtnow=".$dtnow->format("YmdHis"));
if(is_downtime(json_decode($conf["down_calendar"],true),$dtnow)){
$log->write("II - CNT - configuration XX/YY is in downtime");
//do stuff
}else{
//do other stuff
}
日志显示:
17/02/23 16:35:04 : DBG - conf={ ..., "down_calendar":"{\"1\":{\"0\":[\"06:50:00\",\"07:10:00\"]},\"2\":{\"0\":[\"06:50:00\",\"07:10:00\"]},\"3\":{\"0\":[\"06:50:00\",\"07:10:00\"]},\"4\":{\"0\":[\"06:50:00\",\"07:10:00\"]},\"5\":{\"0\":[\"06:50:00\",\"07:10:00\"]},\"6\":{\"0\":[\"06:50:00\",\"07:10:00\"]},\"7\":{\"0\":[\"06:50:00\",\"07:10:00\"]}}", ...}
17/02/23 16:35:04 : DBG - dtnow=20230217163500
17/02/23 16:35:04 : II - CNT - configuration XX/YY is in downtime
事实是,如果在问题出现后使用相同参数执行该函数 100 次,该函数将正确返回“false”。 这个问题不是经常性的,比如每周五16:35,所以很难调试。
这怎么可能? 你能帮我吗,不是解决问题,而是至少了解如何更好地调试问题。
先感谢您。
...
if(is_downtime(json_decode($conf["down_calendar"],true),$dtnow)){
//do stuff
}else{
//do other stuff
}
...
【问题讨论】:
-
无关fyi:
*/5 * * * *每5分钟检查一次 -
我知道......但我更喜欢这种方式,不仅对我来说,因为有时其他用户会阅读 crontab :D
标签: php mysql json logging graph