您的位置:首页 > 编程语言 > PHP开发

使用register_shutdown_function实现php项目脚本执行失败的实时报警

2017-06-15 19:10 676 查看
    背景:当线上php脚本执行失败时,希望能够实时地自动发送报警邮件,而不是等收到用户的反馈才知道有bug存在。
    分析:当我们的php脚本正常执行完成或意外死掉导致PHP执行即将结束时,register_shutdown_function指定的函数将会被调用。
    实现思路:在脚本开始处设置一个变量,值为false,然后在脚本末尾将之设置为true,让PHP关闭回调函数(即我们指定的函数)检查脚本是否已经完成【如果我们的变量仍旧是false,我们就知道脚本的最后一行没有执行,因此它肯定在程序执行到某处死掉了】
     以下是一个演示例子:

1、主入口index.php文件:
<?php
// start
function shutdown_func() { //定义关闭回调函数
    // shutdown
    global $completeFlag;
    global $completeFlagKey;
    if (!$completeFlag) {
        $monitorVal = 'URL地址:'.$_SERVER['REQUEST_URI'].'<br>';
        $monitorVal .= 'GET参数:'.json_encode($_GET).'<br>';
        $monitorVal .= 'POST参数:'.json_encode($_POST).'<br>';
        $monitorVal .= '当前用户:'.$_SESSION['currUserName'].'<br>';

        $monitorVal .= '时间:'.date('Y-m-d H:i:s').'<br>';
        $monitorVal .= '错误信息:'.json_encode(error_get_last());
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $redis->set($completeFlagKey, $monitorVal);
    }
    return false;
}

register_shutdown_function("shutdown_func");
$completeFlag = false;

$completeFlagKey = uniqid('scriptShutdownMonitor_');

/*...这里是其他功能代码...*/

$completeFlag = true;
// end
?>
2、各控制器都集成CommonController,CommonController文件的析构函数:
function __destruct() {
          // destruct
    global $g_curr_run_env;
    global $completeFlagKey;
    if ($g_curr_run_env == 'online') {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $redis->delete($completeFlagKey);
    }
}

注意:__destruct里面如果要操作文件,也要写绝对路径
(1)如果是正常运行完,执行流程为:start 代码 destruct end shutdown
(2)如果是脚本发生error,执行流程为:start 代码 shutdown
(3)如果是代码里面主动exit()或die(),执行流程为:start 代码 shutdown destruct

3、监控报警邮件。通过crontab定时调用
set_time_limit(0);

date_default_timezone_set('Asia/shanghai');
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$keys = $redis->keys('scriptShutdownMonitor_*');
$msg = "";
foreach ($keys as $key) {

  $val = $redis->get($key);

  if ($val) {

     $msg .= $val."<br><hr><br>";

  }

  $redis->del($key);
}
if ($msg != '') {

  $logCon = "当前时间:".date('Y-m-d
H:i:s').";msg:".$msg."\n";

  file_put_contents("send_email.log", $logCon,
FILE_APPEND);

  require_once('send_email.php');
  send_email(
     'xx@qq.com',
     '线上脚本执行失败报警',
     $msg
  );

}

附上博主的个人网站:w3cstudy学习网,上面的有很多供学习文章,有兴趣可以去逛逛

几点说明:
1、 register_shutdown_function('shutdown_func');
    对应回调函数的定义以及这句话要放在有可能引发错误的代码前面,否则在错误代码处崩溃后,这行代码也不会执行
        参数:可以是一个字符串,即指定的关闭回调函数的名称,无需带括号,用引号包住即可; 也可以是一个数组,如array(‘error’,’shutdown_errow’)表示指定error类中的shutdown_error函数为关闭回调函数。

2、exit();//即使使用了exit();也会在exit()执行完后调用register_shutdown_function函数!
3、register_shutdown_function执行机制是:php把要调用的函数调入内存。当页面所有php语句都执行完成时,再调用此函数。注意,在这个时候从内存中调用,不是从php页面中调用,所以上面的例子中回调函数内如果要操作文件不能使用相对路径,因为php已经当原来的页面不存在了。就没有什么相对路 径可言。

4、可以这样理解调用条件:
      (1)当页面被用户代码如exit()强制停止时
      (2)当程序代码运行超时或者出现错误时

      (3)当php代码正常执行完成时
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  php 监控 报警