确定用于评估预处理的PHP.INI值的运行时源?

Lan*_*nce 11 php apache logging

有没有办法通过增强的错误日志消息或输出变量确定运行时使用的CORE PHP DIRECTIVES值的值?这与每个错误的phpinfo()输出相同.

一个基本的例子是error_reporting变量.如果/etc/php.ini值设置为x,并且phpinfo()声明该php.ini文件实际上是ini变量的预期来源.但是如果用户在代码中对该变量实现运行时调整,我们是否能够在抛出错误时输出error_reporting变量.

例如当php.ini文件有E_ALL&〜E_STRICT但日志文件中报告了E_STRICT错误时,有一种方法可以增强输出到日志文件,显示所有系统变量的"堆栈跟踪"可能通过添加到httpd日志的错误ID来激活或至少修改它们的源,以及报告的每个错误的源,该错误ID对应于在错误发生时显示那些运行时设置的可选文件.

我确实认识到可以使用try/catch,但我不相信可以在实际中实现混合第三方代码的大型部署.

这样的机制是否存在于PHP中,或者是否有人开发过(google说不太可能)?通过将变量设置的相关性与错误消息相关联来加速代码库的合并,这对于许多其他错误情况可能是有价值的.

我希望我只是看着这个错误,并且有一个简单的解决方法,我很想念.

谢谢!

Ada*_*dam 7

我终于有了一个完整的"pecl runkit"示例,因为我apd在新的分发版上安装时遇到了麻烦 (这是一个旧的库).

您可以runkit使用PECL 安装它:

 pecl install runkit
Run Code Online (Sandbox Code Playgroud)

并在php.ini中添加以下行:

 extension=runkit.so
 runkit.internal_override=1
Run Code Online (Sandbox Code Playgroud)

我忘了提到 error_reporting可以使用error_reporting()函数或不同的方式定义ini_set.所以我们必须关心每个功能.首先我们复制旧的ini_set使用runkit_function_copy,然后我们使用重新定义它runkit_function_redefine

debug_bactrace(1)用来获取调用文件和行号.

最后要抓住非致命和致命的错误,我们必须使用set_error_handlerregister_shutdown_function.

发生错误后,以下代码将输出ini_set调用的位置和文件名/行.

错误(类型= 2):在文件/var/www/html/test.php第47行中除以零

INI SET堆栈

  • 这里定义了error_reporting(按顺序):
    • /var/www/html/test.php,第16行,值:0
    • /var/www/html/test.php,第17行,值:2
    • /var/www/html/test.php,第18行,值:1
    • /var/www/html/test.php,第19行,价值:32767

码:

<?php
runkit_function_copy("ini_set", "old_ini_set");

runkit_function_redefine("ini_set", '$key,$value', '
    global $iniset;
    $trace=debug_backtrace(1);
    $iniset[$key][]=$trace[0];
    old_ini_set($key, $value);');

runkit_function_redefine("error_reporting", '$value', '
    global $iniset;
    $trace=debug_backtrace(1);
    $iniset["error_reporting"][]=$trace[0];
    old_ini_set($key, $value);');

// let test now
ini_set("error_reporting", 0);
ini_set("error_reporting", E_WARNING);
error_reporting(E_ERROR);
ini_set("error_reporting", E_ALL);

set_error_handler("custom_error_handler");
register_shutdown_function("custom_error_handler");

function custom_error_handler($errno=NULL, $errstr=NULL) {
    global $iniset;
    if (!($error=func_get_args())) {
        $error=error_get_last();
        if ($error!=E_ERROR) $error=NULL;
    }
    if ($error) {
        echo "Error (type=$error[0]): $error[1]\n
            in file $error[2] line $error[3]<br />\n";
        echo "INI SET stack<br />\n";
        echo "<ul>";
        foreach ($iniset as $key=>$val) {
            echo "<li>$key was defined here (in order):<ul>";
            foreach ($val as $def) {
                echo "<li>{$def['file']}, line {$def['line']},
                      value: ".array_pop($def['args'])."</li>";
            }
            echo "</li></ul>";
        }

        echo "</table>";
    }
}

// division by 0
12/0;
Run Code Online (Sandbox Code Playgroud)

上一篇文章:

您可以使用该ini_get_all()函数获取所有本地和全局配置选项的值.

要检索本地值和全局值的值,可以将$details参数设置为true:

ini_get_all(NULL, true);
Run Code Online (Sandbox Code Playgroud)

您可以使用ini_get()(对于运行时值)和get_cfg_var()(对于全局php.ini值)函数获取各个选项的值.

$global_value=get_cfg_var("error_reporting");
$local_value=ini_get("error_reporting");

echo "Error reporting (Local value: $local_value, global value: $global_value)\n"
Run Code Online (Sandbox Code Playgroud)

为了在发生错误时查看这些结果,您必须捕获错误.

对于非致命错误,您可以使用set_error_handler()

对于致命错误,您必须定义shutdown_function(),请参阅如何捕获PHP致命错误