问题 确定用于评估预处理的PHP.INI值的运行时源?
有没有办法通过增强的错误日志消息或输出变量确定运行时使用的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说不太可能)?通过将变量设置的相对性与错误消息相关联,可以帮助加速代码库的合并,这对许多其他错误情况可能有所不同。
我希望我只是看着这个错误,并且有一个简单的解决方法,我很想念。
谢谢!
9423
2018-05-31 18:19
起源
答案:
我终于有了一个完整的“pecl runkit”示例,因为我在安装时遇到了麻烦 apd
在一个新鲜的分布(这是一个旧图书馆)。
你可以安装 runkit
它与PECL:
pecl install runkit
并在php.ini中添加以下行:
extension=runkit.so
runkit.internal_override=1
我忘了提到那个 error_reporting
可以用不同的方式定义 error_reporting()
功能还是 ini_set
。所以我们要关心每个功能。
首先我们复制旧的 ini_set
运用 runkit_function_copy
然后我们使用重新定义它 runkit_function_redefine
我用 debug_bactrace(1)
获取调用文件和行号。
最后要抓住非致命和致命的错误,我们必须使用 set_error_handler
和 register_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;
上一篇文章:
您可以使用以下命令获取所有本地和全局配置选项的值 ini_get_all()
功能。
要检索本地值和全局值的值,可以设置 $details
参数为true:
ini_get_all(NULL, true);
您可以使用。获取各个选项的值 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"
为了在发生错误时查看这些结果,您必须捕获错误。
对于非致命错误,您可以使用 的set_error_han dler()
对于致命错误,您必须定义shutdown_function(),请参阅 我如何捕获PHP致命错误
7
2017-12-06 12:45
答案:
我终于有了一个完整的“pecl runkit”示例,因为我在安装时遇到了麻烦 apd
在一个新鲜的分布(这是一个旧图书馆)。
你可以安装 runkit
它与PECL:
pecl install runkit
并在php.ini中添加以下行:
extension=runkit.so
runkit.internal_override=1
我忘了提到那个 error_reporting
可以用不同的方式定义 error_reporting()
功能还是 ini_set
。所以我们要关心每个功能。
首先我们复制旧的 ini_set
运用 runkit_function_copy
然后我们使用重新定义它 runkit_function_redefine
我用 debug_bactrace(1)
获取调用文件和行号。
最后要抓住非致命和致命的错误,我们必须使用 set_error_handler
和 register_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;
上一篇文章:
您可以使用以下命令获取所有本地和全局配置选项的值 ini_get_all()
功能。
要检索本地值和全局值的值,可以设置 $details
参数为true:
ini_get_all(NULL, true);
您可以使用。获取各个选项的值 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"
为了在发生错误时查看这些结果,您必须捕获错误。
对于非致命错误,您可以使用 的set_error_han dler()
对于致命错误,您必须定义shutdown_function(),请参阅 我如何捕获PHP致命错误
7
2017-12-06 12:45
您可以使用 error_reporting()
没有参数来返回当前的错误报告状态。要测试特定功能,请执行类似操作 error_reporting() & (E_STRICT | E_COMPILE_WARNING)
,这将测试是否 E_STRICT
和 E_COMPILE_WARNING
已启用。
但是,如果你真的想要那样的话 phpinfo()
详细信息,您始终可以捕获phpinfo输出并将其记录到错误日志(或其他地方),并使用html格式。例如:
ob_start();
phpinfo();
error_log(ob_get_clean());
请注意,这只会将phpinfo()写入日志,并且 不 在响应中输出它。
此外,您可能需要考虑使用 Xdebug的。如果您正在寻找更好的堆栈跟踪,这可能会有所帮助。
2
2017-12-05 19:36
你的问题的范围有点不清楚,所以我写了我对PHP的错误处理的了解,并将这个任务理解给你。
检测代码更改php.ini设置
您的部分问题表明您运行的代码意外地将设置从其默认值更改,并且您获得应该已禁用的错误类型。
对此的解决方案是不更改代码中的设置,并找到这些位置,有一个工具: PHP Code Sniffer。它有一个规则“ForbiddenFunction”,可以自定义查找调用 ini_set
, error_reporting
和别的。
您将扫描代码以获取对这些函数的调用,然后分析它们存在的原因。简单地删除它们可能不是正确的解决方案,因为如果代码更改错误设置,则有一个原因。也许代码错误地将值设置回原始值。
在运行时获取设置的当前值
您可以注册在常规代码执行期间执行的回调 register_tick_function。它将被称为每个“滴答”数,这是低级语句的数量。实际上,您可以使注册函数几乎在每个常规脚本语句之后跳转 - 请注意,这将影响运行时。
函数本身可以尝试分析您喜欢的任何内容,并对变化做出反应。
在出现错误/异常时获取当前值
您可以注册自己的错误和异常处理程序。 的set_error_han dler 接受将被调用的回调,其中包含有关触发的任何错误的所有信息(不包括致命错误 - 如果PHP引擎失败,例如语法错误,则不能再调用任何内容)。
bool handler (
int $errno ,
string $errstr
[, string $errfile
[, int $errline
[, array $errcontext
]]]
)
无论使用哪种设置,都将调用该函数 error_reporting()
已被选中,但它也可以读取设置并忽略具有禁用错误的调用。所以在你的情况下,它可以读取全局php.ini设置(或让它硬编码)并忽略所有其他错误。或者在特殊日志文件中报告这些错误。返回 false
从这个函数将调用常规错误处理,返回 true
将继续,好像什么也没发生。
可以通过以下方式访问全局变量 $GLOBALS
阵列。
未被捕获的抛出异常将由注册的回调处理 set_exception_handler。回调将获得异常对象,其中包含从消息到堆栈跟踪的所有内容。
现在?
修复代码怎么样?严格的错误有一个原因:更新PHP时,您的代码可能会中断。你没有提供细节,所以这必须是一个通用的建议,但我想知道你的问题的背景是什么。我有一种感觉,你提出错误的问题或试图在地毯下擦除代码问题。你可以做到这一点,但它最终会受到伤害 - 如果目前的情况已经受到伤害,它会在以后受到伤害。转到我的第一个建议:找到代码中的问题并适当地修复它们。其他一切都不是修复代码,而是减少它的错误日志占用空间。
2
2017-12-06 13:36