如何从错误日志文件中获取每个错误?

How to get each error from error log file?

我想在日志错误文件中获取每个错误。

所以如果文件包含:

[08-Jul-2018 08:12:04 UTC] PHP Fatal error:  Call to undefined method DateTime::fomat() in C:\xampp\htdocs\wordpress\wp-content\themes\theme\index.php on line 44

[08-Jul-2018 08:22:22 UTC] PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'database.table' doesn't exist' in C:\xampp\htdocs\wordpress\wp-content\themes\theme\index.php:37
Stack trace:
#0 C:\xampp\htdocs\wordpress\wp-content\themes\news_theme\index.php(37): 
PDOStatement->execute()
#1 C:\xampp\htdocs\wordpress\wp-includes\template-loader.php(74): 
include('C:\xampp\htdocs...')
#2 C:\xampp\htdocs\wordpress\wp-blog-header.php(19): 
require_once('C:\xampp\htdocs...')
#3 C:\xampp\htdocs\wordpress\index.php(17): require('C:\xampp\htdocs...')
#4 {main}
thrown in C:\xampp\htdocs\wordpress\wp-content\themes\theme\index.php on line 37

这是两个错误,但其中一个很长,超过一行。

我想把它们的每一个错误都放在一个变量中。

我试过了:

$contents  = file(get_template_directory().'/errors.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($contents as $key => $content) {
    echo $key . $content . '<br>';
}

但这会获取每一行,因此第二行将存储在几个变量中,我想在一个变量中获取每个错误。

这可能吗?

您的代码只是打印 每个 输入行及其编号。

为了将输入分成块,关于每个错误,你可以采取 以下方法:

  • 整个文件读入变量。
  • 执行例如preg_match_all就可以了。

要使用的正则表达式应该匹配:

  • ^\[[^\]]+\] - 初始部分 - 括号之间的日期/时间,从 行首(由于 m 选项)。
  • [^\n]+ - \n 以外的字符序列 - 这一行的其余部分。

现在剩下的 - 可选的非捕获组 - (?:...)?,包含:

  • \nStack trace: - "longer" 消息的开始部分,再次 从行首开始。
  • .+ - "middle part" - 堆栈跟踪的实际内容。 由于 s 选项,它也匹配 \n 个字符,结束这些 "middle" 行。
  • \nthrown - 要匹配的最后一行 - 从行首抛出
  • .+?$ - 任意数量的任意字符,直到本(最后)行的末尾。

要匹配多行和每行的开始/结束, 使用 ms 正则表达式选项。

下面有一个示例程序,匹配常量文本,而不是 输入文件:

<?php
$text = <<<'EOD'
[08-Jul-2018 08:12:04 UTC] PHP Fatal error: on line 44
[08-Jul-2018 08:22:22 UTC] PHP Fatal error: in ...:37
Stack trace:
#0 C:\xampp\htdocs\wordpress\wp-content\themes\news_theme\index.php(37): 
PDOStatement->execute()
#1 C:\xampp\htdocs\wordpress\wp-includes\template-loader.php(74): 
include('C:\xampp\htdocs...')
thrown in ... on line 37
[08-Jul-2018 08:12:45 UTC] PHP Fatal error: on line 155
EOD;

$pattern = '/^\[[^\]]+\]\D+\d+\n(?:Stack trace:.+\nthrown.+?$)?/ms';
if (preg_match_all($pattern, $text, $matches))
    print_r($matches[0]);
?>

根据需要它只打印 3 个匹配项。

编辑

如果您还有其他错误情况,请尝试另一个正则表达式:

^\[[^\]]+\][^\n]+(?:\n[^\[\n][^\n]+)*

这次,只有 m 选项。它匹配:

  • ^\[[^\]]+\][^\n]+ - "starting" 行 - [...]....
  • (?:\n[^\[\n][^\n]+)* - 任意数量(包括0)的非空以下 行,不是从 [.
  • 开始

有关最后一个正则表达式的工作示例,请参阅 https://regex101.com/r/0IUkc0/1

将文件作为 单个字符串 file_get_contents 读取,然后使用

$splits = preg_split('/\s+(?=^\[\d{2}-\w{3}-\d{4} \d+(?::\d{2}){2} \w{3}])/m', $contents);

模式匹配

  • \s+ - 1+ 白色spaces 后跟...
  • (?=^\[\d{2}-\w{3}-\d{4} \d+(?::\d{2}){2} \w{3}]) - 正前瞻,紧靠当前位置的右侧,需要:
    • ^ - 行首(由于 m 修饰符)
    • \[ - 一个 [ 字符
    • \d{2}-\w{3}-\d{4} - 2 位数字,-,3 个字符,-,4 位数字
    • - 一个space
    • \d+ - 1+ 位数
    • (?::\d{2}){2} - 出现 2 次 : 和 2 个数字(与 :\d{2}:\d{2} 相同)
    • - 一个space
    • \w{3} - 3 个单词字符(字母、数字或 _
    • ] - 一个 ] 字符。

参见regex demo