给新手的一些建议:此函数与“tail”配合使用效果很好,“tail”是用于实时监视日志文件的 Unix 命令。Windows 也有一些 Tail 版本,例如 Tail for Win32 或 Kiwi Log Viewer。
通过同时使用 error_log() 和 tail 查看 php_error.log,您可以调试代码,而无需过多担心将调试消息打印到屏幕上以及谁可能看到它们。
进一步说明:当您设置了两个显示器时,效果会更好。一个用于浏览器和 IDE,另一个用于实时查看日志文件更新。
(PHP 4, PHP 5, PHP 7, PHP 8)
error_log — 将错误消息发送到已定义的错误处理例程
$message
,$message_type
= 0,$destination
= null
,$additional_headers
= null
将错误消息发送到 Web 服务器的错误日志或文件。
message
要记录的错误消息。
message_type
指定错误应该发送到哪里。可能的 message_type 如下所示
0 |
message 使用操作系统的系统日志机制或文件发送到 PHP 的系统日志程序,具体取决于 error_log 配置指令的设置。这是默认选项。 |
1 |
message 通过电子邮件发送到 destination 参数中的地址。这是唯一一个使用第四个参数 additional_headers 的 message_type。 |
2 | 不再是选项。 |
3 |
message 附加到文件 destination 。不会自动在 message 字符串末尾添加换行符。 |
4 |
message 直接发送到 SAPI 日志处理程序。 |
destination
目标。其含义取决于上面描述的 message_type
参数。
additional_headers
额外的报头。当 message_type
参数设置为 1
时使用。此 message_type 使用与 mail() 相同的内部函数。
版本 | 描述 |
---|---|
8.0.0 |
destination 和 additional_headers 现在可以为空。 |
示例 #1 error_log() 示例
<?php
// 如果无法连接到数据库,则通过服务器日志发送通知。
if (!Ora_Logon($username, $password)) {
error_log("Oracle 数据库不可用!", 0);
}
// 如果用完 FOO,则通过电子邮件通知管理员
if (!($foo = allocate_new_foo())) {
error_log("大麻烦,我们所有的 FOO 都用完了!", 1,
"[email protected]");
}
// 另一种调用 error_log() 的方法:
error_log("你搞砸了!", 3, "/var/tmp/my-errors.log");
?>
error_log() 不是二进制安全的。 message
将会被空字符截断。
message
不应包含空字符。请注意, message
可能会发送到文件、邮件、syslog 等。在调用 error_log() 之前,使用适当的转换/转义函数,如 base64_encode()、rawurlencode() 或 addslashes()。
给新手的一些建议:此函数与“tail”配合使用效果很好,“tail”是用于实时监视日志文件的 Unix 命令。Windows 也有一些 Tail 版本,例如 Tail for Win32 或 Kiwi Log Viewer。
通过同时使用 error_log() 和 tail 查看 php_error.log,您可以调试代码,而无需过多担心将调试消息打印到屏幕上以及谁可能看到它们。
进一步说明:当您设置了两个显示器时,效果会更好。一个用于浏览器和 IDE,另一个用于实时查看日志文件更新。
不要尝试在 error_log() 中输出过长的文本;
如果您尝试输出大量文本,它要么会在大约 8000 个字符处截断文本(对于合理的大量字符串,< 32K 个字符),要么(对于非常大的字符串,大约 160 万个字符)完全崩溃,甚至不会抛出任何错误或任何内容(我甚至将其放在 try/catch 中,但没有从 catch 中获得任何结果)。
当我尝试调试 wp_remote_get() 的响应时遇到了这个问题;我所有的 error_log() 都按预期工作,除了其中一个...(-_-)
经过大约一天的调试,我终于找到了原因,所以在这里写下这个。
显然,响应包含一个主体,其中包含超过 160 万个字符(或字节?(无论 strlen() 返回什么))。
如果您有一个长度未知的字符串,请使用以下代码
$start_index = 0;
$end_index = 8000;
error_log( substr( $output_text , $start_index , $end_index ) );
您可以作为 $message 传递的最大长度是有限制的。
默认值似乎为 1024,但可以通过调整“log_errors_max_len”的运行时配置值的来更改。
更多详细信息请参阅
https://php.net/manual/en/errorfunc.configuration.php
小心!如果多个脚本共享同一个日志文件,但以不同的用户身份运行,那么第一个记录错误的脚本将拥有该文件,而以其他用户身份运行的 error_log() 调用将*静默*失败!
没有什么比试图找出为什么所有 error_log 调用实际上都没有写入更令人沮丧的了,然后发现这是由于一个*静默*的权限被拒绝错误造成的!
如果从命令行运行 PHP,则系统日志似乎等于标准错误,并且标准错误通常等于标准输出。这意味着,如果您使用自定义错误来显示错误并将其记录到系统日志中,则命令行用户将看到相同的错误报告两次。
相对路径被接受为 message_type 3 的目标,但请注意,根目录由对 error_log() 的调用的上下文确定,该上下文可能会更改,因此代码中 error_log() 的一个实例可能导致在不同位置创建多个日志文件。
在 WordPress 上下文中,根目录在许多情况下将是站点的根目录,但对于 AJAX 调用,它将是 /wp-admin/,而在其他情况下则为插件的目录。如果您希望所有输出都转到一个文件,请使用绝对路径。
当使用 error_log 发送电子邮件时,并非 extra_headers 字符串的所有元素都以相同的方式处理。“From: ”和“Reply-To: ”标题值将替换默认标题值。“Subject: ”标题值不会替换:它们会被*添加到*邮件标题中,但不会替换默认标题,从而导致邮件包含两个 Subject 字段。
<?php
error_log("sometext", 1, "[email protected]",
"Subject: Foo\nFrom: [email protected]\n");
?>
---------------%<-----------------------
To: [email protected]
Envelope-to: [email protected]
Date: Fri, 28 Mar 2003 13:29:02 -0500
From: [email protected]
Subject: PHP error_log message
Subject: Foo
Delivery-date: Fri, 28 Mar 2003 13:29:03 -0500
sometext
---------------%<---------------------
文档中写道:“此消息类型使用与 mail() 相同的内部函数。”
mail() 也会无法根据 extra_header 数据设置 Subject 字段 - 而是采用单独的参数来指定“Subject: ”字符串。
php v.4.2.3,SunOS 5.8
在 *nix 系统上,您可以使用“tail”和“grep”轻松过滤发送到 error_log() 的消息。这使得在开发过程中监控调试消息变得容易。
请确保使用唯一的字符串“标记”您的错误消息,以便您可以使用“grep”进行过滤。
在您的代码中
error_log("DevSys1 - FirstName: $FirstName - LastName: $Lastname");
在您的命令行中
tail -f /var/log/httpd/error_log | grep DevSys1
在此示例中,我们将 apache 日志输出传递给 grep(STDIN),它为您过滤输出,仅显示包含“DevSys1”的消息。
“-f”选项表示“跟随”,它将所有新的日志条目流式传输到您的终端或任何后续的管道命令,在本例中为“grep”。
“如果从命令行运行 PHP,则系统日志似乎等于标准错误”
实际上,如果 PHP 无法写入日志文件,它似乎会记录到标准错误。命令行 PHP 会回退到标准错误,因为日志文件(通常)仅对 Web 服务器可写。
在 Windows 上记录到 Apache 时,error_log 和 trigger_error 都会导致 Apache 状态在消息前面显示错误。如果只想记录信息,这很糟糕。但是,您可以简单地记录到标准错误,但是您必须进行所有消息组装
LogToApache($Message) {
$stderr = fopen('php://stderr', 'w');
fwrite($stderr,$Message);
fclose($stderr);
}
你好!
另一个发布“HTML”邮件正文的技巧。只需将“Content-Type: text/html; charset=ISO-8859-1”添加到 extra_header 字符串中。当然,您可以根据您的国家/地区或环境或内容设置字符集。
例如:Error_log("<html><h2>stuff</h2></html>",1,"[email protected]","subject :lunch\nContent-Type: text/html; charset=ISO-8859-1");
享受!
如果在 error_log 文件中找不到您的条目
当您在不产生任何输出的脚本中使用 error_log 时,这意味着您无法在脚本执行期间看到任何内容,并且当您想知道为什么在 error_log 文件中没有生成 error_log 条目时,原因可能是
- 您没有在 php.ini 中配置 error_log 输出。
- 脚本存在语法错误,因此未执行。
请注意,由于典型的电子邮件未加密,因此使用此函数通过电子邮件发送有关错误的数据可能被视为安全风险。风险的大小取决于您发送的信息量和类型,但即使在发生某些事情时发送电子邮件(即使无法读取)本身也可能暗示高级黑客长时间观察您的网站,表明他们已设法导致错误。
当然,通过模糊来实现安全是最弱的安全类型,正如大多数开源支持者所同意的。这只是您应该记住的事情。
当然,无论您做什么,请确保此类电子邮件不包含敏感的用户数据。
<?php
//多行错误日志类
// ersin güvenç 2008 [email protected]
//要换行请使用“\n”而不是'\n'
类 log {
//
常量 USER_ERROR_DIR = '/home/site/error_log/Site_User_errors.log';
常量 GENERAL_ERROR_DIR = '/home/site/error_log/Site_General_errors.log';
/*
用户错误...
*/
公共函数 user($msg,$username)
{
$date = date('d.m.Y h:i:s');
$log = $msg." | 日期: ".$date." | 用户: ".$username."\n";
error_log($log, 3, self::USER_ERROR_DIR);
}
/*
一般错误...
*/
公共函数 general($msg)
{
$date = date('d.m.Y h:i:s');
$log = $msg." | 日期: ".$date."\n";
error_log($msg." | 日期: ".$date, 3, self::GENERAL_ERROR_DIR);
}
}
$log = new log();
$log->user($msg,$username); //用于用户错误
//$log->general($msg); //用于一般错误
?>
如果您在日志文件权限方面遇到*静默*问题
最好将 error_log 指令保留为空,以便错误将写入当前虚拟主机的 Apache 日志文件中。
当 error_log() 意外地使用标准输出时,您应该检查 CLI 环境中 php.ini 中 error_log 的值是否为空。像这样简单的操作可能会恢复预期的行为
<?php ini_set('error_log', 'error_log'); ?>
// 用于记录信息的漂亮函数
<?php
function logger($log, $clear = true){
file_put_contents('/path/log/logger.log', (is_object($log) || is_array($log) || is_resource($log) ? json_encode($log, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : $log), (!$clear) ? FILE_APPEND : 0);
}