php 我可以捕获exit()和die()消息吗?

ff29svar  于 2023-01-16  发布在  PHP
关注(0)|答案(8)|浏览(233)

我希望能够捕获die()exit()消息。这可能吗?我希望类似于set_error_handlerset_exception_handler的东西。我已经查看了register_shutdown_function(),但它似乎不包含令人不快的die()exit()调用的上下文。
我意识到die()exit()是处理错误的坏方法。我不希望被告知不要这样做。:)我正在创建一个通用系统,希望能够优雅地记录exit()die(),如果出于某种原因有人(不是我)认为这是一个好主意。

tag5nh1u

tag5nh1u1#

是的,您可以,但是您需要ob_startob_get_contentsob_end_clean注册关闭函数

function onDie(){
    $message = ob_get_contents(); // Capture 'Doh'
    ob_end_clean(); // Cleans output buffer
    callWhateverYouWant();
}
register_shutdown_function('onDie');
//...
ob_start(); // You need this to turn on output buffering before using die/exit
@$dumbVar = 1000/0 or die('Doh'); // "@" prevent warning/error from php
//...
ob_end_clean(); // Remember clean your buffer before you need to use echo/print
mrwjdhj3

mrwjdhj32#

根据PHP manual,调用die()或exit()时仍应通知关断函数。
Shutdown functions和对象析构函数将始终执行,即使调用了exit()。
似乎不可能在exit($status)中得到状态信息,除非你可以使用输出缓冲来捕获它,但是我不知道你怎么知道什么时候调用ob_start()

hpcdzsge

hpcdzsge3#

如果APD可用,override_function()可能会很有趣

7uhlpewt

7uhlpewt4#

据我所知,这是不可能的。这里发布的一些解决方案可能有效,但它们需要大量额外的工作或许多依赖项。没有办法轻松可靠地捕获die()和exit()消息。

f4t66c6m

f4t66c6m5#

为什么不用自定义错误处理呢?如果不用,你可以使用LD_PRELOAD和C代码注入来捕获它:)或者用你的自定义重新编译php:P

4c8rllxm

4c8rllxm6#

如果您使用单点输入方法.(index.php),我建议您使用以下方法进行错误处理:

    • 简短版本:**
ob_start();
register_shutdown_function('shutdownHandler');

include('something');

define(CLEAN_EXIT, true);

function shutdownHandler() {
    if(!defined("CLEAN_EXIT") || !CLEAN_EXIT) {
        $msg = "Script stopped unexpectedly: ".ob_get_contents();
        //Handle premature die()/exit() here
    }
}
    • 其他步骤和更多详细信息:**

这大概是我的工作方式。我做的事情比这里展示的还要多(处理数据库事务/回滚/发送电子邮件/写日志/显示友好的错误消息/用户错误报告/等等),但这是所有这些事情背后的基本思想)。
希望能帮上忙。

<?php

    //Some initialization

    //starting output buffering. (fatalErrorHandler is optional, but I recommend using it) 
    ob_start('fatalErrorHandler');

    //Execute code right at the end. Catch exit() and die() here. But also all other terminations inside PHPs control
    register_shutdown_function('shutdownHandler');

    //handling other errors: Also optional
    set_error_handler('errorHandler');


    try {
        //Include of offensive code
        include(...);
    }
    catch (Exception $ex) {
        //Handling exception. Be careful to not raise exceptions here again. As you can end up in a cycle. 
    }

    //Code reached this point, so it was a clean exit.
    define(CLEAN_EXIT, true);

    //Gets called when the script engine shuts down.
    function shutdownHandler() {

        $status = connection_status();

        $statusText = "";

        switch ($status) {
            case 0:
                if (!defined("CLEAN_EXIT") || !CLEAN_EXIT) {
                                    $msg = "Script stopped unexpectedly: ".ob_get_contents();
                    //Handle premature die()/exit() here
                }
                else {
                    //Clean exit. Just return
                    return;
                }
            case 1: $statusText = "ABORTED (1)"; break;
            case 2: $statusText = "TIMEOUT (2)"; break;
            case 3: $statusText = "ABORTED & TIMEOUT (3)"; break;

            default : $statusText = "UNKNOWN ($status)"; break;
        }

        //Handle other exit variants saved in $statusText here ob_get_contents() can have additional useful information here
    }

    // error handler function  (This is optional in your case)
    function errorHandler($errno, $errstr, $errfile, $errline) {

        $msg = "[$errno] $errstr\nOn line $errline in file $errfile";

        switch ($errno) {
            case E_ERROR:               $msg = "[E_ERROR] ".$msg;               break;
            case E_WARNING:             $msg = "[E_WARNING] ".$msg;             break;
            case E_PARSE:               $msg = "[E_PARSE] ".$msg;               break;
            case E_NOTICE:              $msg = "[E_NOTICE] ".$msg;              break;
            case E_CORE_ERROR:          $msg = "[E_CORE_ERROR] ".$msg;          break;
            case E_CORE_WARNING:        $msg = "[E_CORE_WARNING] ".$msg;        break;
            case E_COMPILE_ERROR:       $msg = "[E_COMPILE_ERROR] ".$msg;       break;
            case E_COMPILE_WARNING:     $msg = "[E_COMPILE_WARNING] ".$msg;     break;
            case E_USER_ERROR:          $msg = "[E_USER_ERROR] ".$msg;          break;
            case E_USER_WARNING:        $msg = "[E_USER_WARNING] ".$msg;        break;
            case E_USER_NOTICE:         $msg = "[E_USER_NOTICE] ".$msg;         break;
            case E_STRICT:              $msg = "[E_STRICT] ".$msg;              break;
            case E_RECOVERABLE_ERROR:   $msg = "[E_RECOVERABLE_ERROR] ".$msg;   break;
            case E_DEPRECATED:          $msg = "[E_DEPRECIATED] ".$msg;         break;
            case E_USER_DEPRICIATED:    $msg = "[E_USER_DEPRICIATED] ".$msg;    break;
            default:                    $msg = "[UNKNOWN] ".$msg;               break;
        }

        //Handle Normal error/notice/warning here. 
        $handled = ...

        if ($handled)
            return true; //handled. Proceed execution
        else
            throw Exception($msg); //Be careful. this might quickly become cyclic. Be sure to have code that catches and handles exceptions. Else die() here after logging/reporting the error.

    }

    function fatalErrorHandler(&$buffer) {

        $matches = null;
        //Checking if the output contains a fatal error
        if (preg_match('/<br \/>\s*<b>([^<>].*)error<\/b>:(.*)<br \/>$/', $buffer, $matches) ) {

            $msg = preg_replace('/<.*?>/','',$matches[2]);

            //Handle Fatal error here

            return "There was an unexpected situation that resulted in an error. We have been informed and will look into it."
         }

         //No fatal exception. Return buffer and continue
         return $buffer;
    }
e5nqia27

e5nqia277#

可能会抛出一个运行时异常,而不是直接调用exit。

<?php

class CatchableExit extends RuntimeException
{
}

class Quitter
{
    public function run($i)
    {
        echo "Quitter called with \$i = $i \n";
        throw new CatchableExit();
    }
}

class Runner
{
    public function run()
    {
        trigger_error('I am a harmless warning', E_USER_WARNING);
        trigger_error('And I am a notice', E_USER_NOTICE);
        for ($i = 0; $i < 10; $i++) {
            $q = new Quitter();
            try {
                $q->run($i);
            } catch (CatchableExit $e) {
            }
        }
    }
}

function exception_handler(Throwable $exception)
{
    if ($exception instanceof CatchableExit) {
        exit();
    }
}

set_exception_handler('exception_handler');

$runner = new Runner();
$runner->run();
bkhjykvo

bkhjykvo8#

是的:编写一个函数并使用它。

function kill($msg){
    // Do your logging..
    exit($msg);
}

相关问题