PHP 过滤指定时间段内的日志

在查阅 服务器上日志文件的时候的,对于小的日志文件 可以直接打开浏览即可,但是对于较大文件 几十 上百兆的,查找日志就没有那么方便了。

特别是查找某一时间段内的日志,对于其他无关内容是,如果全都下载是十分浪费时间的行为,所以就有了本文这段代码。

用于在大的日志文件中查找指定时间段内的 日志内容并返回。

<?php

// 在 error.txt 文件内提取 2024-03-09 0:00:00 至 2024-03-09 23:59:59 时间段内的 php 错误日志
print_r(_filterLogs('error.txt', '2024-03-09 0:00:00', '2024-03-09 23:59:59'));

/**
 * 返回指定文件指定时间段内的 内容
 *
 * @param  string $file         日志文件路径
 * @param  string|int $start    开始时间 日期字符串 或 者时间戳
 * @param  string|int $end      结束时间 格式同上
 * @param  string $rule         日期匹配规则
 * @return array                返回数组 [2, '*******']  0:出现次数  1:搜索结果字符串
 */
function _filterLogs($file, $start, $end, $rule = '/^[ \d\.\-]*?\[(?<date>[^\]]+)/'){
    if(!is_file($file)){
        throw new \Exception('文件不存在');
    }
    $start = is_numeric($start) ? floatval($start) : strtotime($start);
    $end = is_numeric($end) ? floatval($end) : strtotime($end);
    if($start > 1 && $end > 1 && $start <= $end){
        if(is_string($rule) && preg_match('/\(?<(date|time)>/', $rule)){
            // 存储最终结果
            $content = '';
            $number = 0;

            // 存储 文本块
            $block = '';

            // 在时间段内
            $in_times = false;
            $date = '';
            foreach (_filterLogsYieldFile($file) as $line) {
                if(preg_match($rule, $line, $time)){
                    if($block !== '' && $in_times){
                        $content .= $date . $block;
                        $number ++;
                    }
                    $block = "$line\n";
                    if(isset($time['date'])){
                        $time = strtotime($time['date']);
                        if($time && $time > 1){
                            $in_times = $time >= $start && $time <= $end;
                            // $date = date('Y-m-d H:i:s', $time);
                            continue;
                        }else{
                            throw new \Exception('解析时间失败');
                        }
                    }
                    if(isset($time['time'])){
                        $baseTimes[] = floatval($time['time']);
                        if($time && $time > 1){
                            $in_times = $time >= $start && $time <= $end;
                            // $date = date('Y-m-d H:i:s', $time);
                            continue;
                        }else{
                            throw new \Exception('解析时间失败');
                        }
                    }
                    $in_times = false;
                }elseif($block !== ''){
                    $block .= "$line\n";
                }
            }
            return [
                $number,
                $content,
            ];
        }else{
            throw new \Exception('规则不正确');
        }
    }else{
        throw new \Exception('开始 或 结束时间不正确');
    }
}

// 使用迭代器读取文件
function _filterLogsYieldFile($path) {
    $handle = fopen($path, "r");
    while(!feof($handle)) {
        yield trim(fgets($handle));
    }
    fclose($handle);
}

执行后正常将会返回 error.txt 自定时间段内的日志信息


Array
(
    [0] => 13
    [1] => [09-Mar-2024 18:02:15 PRC] PHP Deprecated:  setcookie(): Passing null to parameter #2 ($value) of type string is deprecated in /var/www/test.php on line 74
[09-Mar-2024 21:25:40 PRC] PHP Warning:  finfo_file(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:25:40 PRC] PHP Warning:  readfile(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:25:45 PRC] PHP Warning:  finfo_file(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:25:45 PRC] PHP Warning:  fopen(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:25:45 PRC] PHP Fatal error:  Uncaught TypeError: fseek(): Argument #1 ($stream) must be of type resource, bool given in /var/www/test.php:74
Stack trace:
#0 /var/www/test.php(74): fseek()
#1 /var/www/test.php(74): Test->j()
#2 /var/www/test.php(60): Test->api()
#3 {main}
thrown in /var/www/test.php on line 74
[09-Mar-2024 21:26:06 PRC] PHP Warning:  finfo_file(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:26:06 PRC] PHP Warning:  fopen(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:26:06 PRC] PHP Fatal error:  Uncaught TypeError: fseek(): Argument #1 ($stream) must be of type resource, bool given in /var/www/test.php:74
Stack trace:
#0 /var/www/test.php(74): fseek()
#1 /var/www/test.php(74): Test->j()
#2 /var/www/test.php(60): Test->api()
#3 {main}
thrown in /var/www/test.php on line 74
[09-Mar-2024 21:26:18 PRC] PHP Warning:  finfo_file(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:26:18 PRC] PHP Warning:  fopen(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74
[09-Mar-2024 21:26:18 PRC] PHP Fatal error:  Uncaught TypeError: fseek(): Argument #1 ($stream) must be of type resource, bool given in /var/www/test.php:74
Stack trace:
#0 /var/www/test.php(74): fseek()
#1 /var/www/test.php(74): Test->j()
#2 /var/www/test.php(60): Test->api()
#3 {main}
thrown in /var/www/test.php on line 74
[09-Mar-2024 21:26:35 PRC] PHP Warning:  copy(/var/log/xxxxx.log): Failed to open stream: Permission denied in /var/www/test.php on line 74

)

如果时间不正确,请设置 PHP 默认时区

注意返回数组的第一个值不一定等于 返回的日志内容的行数, 除非所记录的内容皆为单行日志

获取 Nginx 访问日志,返回内容

<?php

// 获取 Nginx 日志
print_r(_filterLogs('access.log', '2024-03-11 0:00:00', '2024-03-11 0:02:00'));

Array
(
    [0] => 35
    [1] => 61.1*.*.* - - [11/Mar/2024:00:00:08 +0800] "GET /weather/gaode/?callback=jQuery33107363490925082734_1708217012262&_=1708217022586 HTTP/1.1" 302 116 "http://************/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0" "-"
219.2*.*.* - - [11/Mar/2024:00:00:19 +0800] "GET /today/list/ HTTP/1.1" 200 885 "-" "okhttp/3.10.0" "-"
183.1*.*.* - - [11/Mar/2024:00:00:26 +0800] "GET /weather/baidu/?city=%E5%B1%B1%E4%B8%9C%E6%B3%B0%E5%AE%89 HTTP/1.1" 200 1161 "-" "-" "-"
14.1*.*.* - - [11/Mar/2024:00:00:30 +0800] "GET /weather/baidu HTTP/1.1" 200 350 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_7_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app" "-"
60.2*.*.* - - [11/Mar/2024:00:00:31 +0800] "GET /weather/baidu HTTP/1.1" 200 373 "-" "Mozilla/5.0 (Linux; Android 13; V2219A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046269 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/32.0)" "-"
120.2*.*.* - - [11/Mar/2024:00:00:31 +0800] "GET /weather/baidu HTTP/1.1" 200 350 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app" "-"
218.6*.*.* - - [11/Mar/2024:00:00:34 +0800] "GET /today/list/ HTTP/1.1" 200 885 "-" "okhttp/3.10.0" "-"
223.7*.*.* - - [11/Mar/2024:00:00:37 +0800] "GET /weather/baidu HTTP/1.1" 200 379 "-" "Mozilla/5.0 (Linux; Android 13; V2278A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046278 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/32.0)" "-"
118.2*.*.* - - [11/Mar/2024:00:00:40 +0800] "GET /jquery.js,jquery.backstretch.min.js HTTP/1.1" 200 34314 "http://************/" "Mozilla/5.0 (Linux; U; Android 12; zh-cn; OXF-AN00 Build/HUAWEIOXF-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.86 MQQBrowser/14.8 Mobile Safari/537.36 COVC/046915" "-"
120.8*.*.* - - [11/Mar/2024:00:00:44 +0800] "GET /weather/baidu HTTP/1.1" 200 402 "-" "Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046279 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/32.363636)" "-"
60.2*.*.* - - [11/Mar/2024:00:00:45 +0800] "GET /weather/baidu HTTP/1.1" 200 373 "-" "Mozilla/5.0 (Linux; Android 13; V2219A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046269 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/32.0)" "-"
125.7*.*.* - - [11/Mar/2024:00:00:49 +0800] "GET /weather/baidu HTTP/1.1" 200 387 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/44) uni-app" "-"
113.1*.*.* - - [11/Mar/2024:00:00:54 +0800] "GET /weather/baidu HTTP/1.1" 200 399 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/44) uni-app" "-"
221.2*.*.* - - [11/Mar/2024:00:00:58 +0800] "GET /weather/gaode/?callback=jQuery35105808790419766503_1708043147214&_=1708043154026 HTTP/1.1" 302 118 "http://************/sense-admin-1.0-SNAPSHOT/a/screen/show" "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-"
111.2*.*.* - - [11/Mar/2024:00:00:59 +0800] "GET /weather/gaode/?callback=jQuery33106603039911879256_1710086456720&_=1710086456721 HTTP/1.1" 200 407 "http://************/jushi_zkdp/pages/jushi_zkdp.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36" "-"
8.1*.*.* - - [11/Mar/2024:00:01:01 +0800] "GET /weather/weather?city=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81\xE5\xB9\xBF\xE5\xB7\x9E\xE5\xB8\x82\xE7\x95\xAA\xE7\xA6\xBA\xE5\x8C\xBA HTTP/1.1" 200 2428 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)" "-"
8.1*.*.* - - [11/Mar/2024:00:01:01 +0800] "GET /weather/weather?city=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81\xE5\xB9\xBF\xE5\xB7\x9E\xE5\xB8\x82\xE7\x95\xAA\xE7\xA6\xBA\xE5\x8C\xBA HTTP/1.1" 200 2428 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)" "-"
8.1*.*.* - - [11/Mar/2024:00:01:01 +0800] "GET /weather/weather?city=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81\xE5\xB9\xBF\xE5\xB7\x9E\xE5\xB8\x82\xE7\x95\xAA\xE7\xA6\xBA\xE5\x8C\xBA HTTP/1.1" 200 2428 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)" "-"
8.1*.*.* - - [11/Mar/2024:00:01:01 +0800] "GET /weather/weather?city=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81\xE5\xB9\xBF\xE5\xB7\x9E\xE5\xB8\x82\xE7\x95\xAA\xE7\xA6\xBA\xE5\x8C\xBA HTTP/1.1" 200 2428 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)" "-"
183.1*.*.* - - [11/Mar/2024:00:01:01 +0800] "GET /weather/baidu/?city=%E5%A4%AA%E5%8E%9F%E5%B8%82&callback=jQuery110201097628486169493_1709884435203&_=1709884435317 HTTP/1.1" 200 439 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" "-"
221.2*.*.* - - [11/Mar/2024:00:01:04 +0800] "GET /weather/gaode/?callback=jQuery35107903800043957159_1708043153044&_=1708043159856 HTTP/1.1" 302 117 "http://************/sense-admin-1.0-SNAPSHOT/a/screen/show" "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-"
113.5*.*.* - - [11/Mar/2024:00:01:05 +0800] "POST /weather/gaode HTTP/1.1" 200 373 "-" "Apache-HttpClient/4.5.13 (Java/1.8.0_221)" "-"
120.2*.*.* - - [11/Mar/2024:00:01:13 +0800] "GET /weather/gaode/?callback=jQuery35109708486405920125_1708043162256&_=1708043169068 HTTP/1.1" 200 410 "http://************/sense-admin-1.0-SNAPSHOT/a/screen/show" "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-"
223.1*.*.* - - [11/Mar/2024:00:01:13 +0800] "GET /weather/baidu HTTP/1.1" 200 350 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 12_5_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app" "-"
219.1*.*.* - - [11/Mar/2024:00:01:21 +0800] "GET /weather/baidu/?ak=adfdb863ddb1101bb6b40c0700d6203b&callback=jsonp_248e3b0f97369a0 HTTP/1.1" 200 405 "http://************/egh/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" "-"
60.2*.*.* - - [11/Mar/2024:00:01:21 +0800] "GET /weather/baidu HTTP/1.1" 200 373 "-" "Mozilla/5.0 (Linux; Android 13; V2219A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046269 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/32.0)" "-"
221.2*.*.* - - [11/Mar/2024:00:01:22 +0800] "GET /weather/gaode/?callback=jQuery35108978902950323038_1708043171213&_=1708043178025 HTTP/1.1" 302 117 "http://************/sense-admin-1.0-SNAPSHOT/a/screen/show" "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-"
36.1*.*.* - - [11/Mar/2024:00:01:29 +0800] "GET /weather/baidu/?city=%E6%9E%9D%E6%B1%9F%E5%B8%82 HTTP/1.1" 200 400 "https://************/weather/?city=%E6%9E%9D%E6%B1%9F%E5%B8%82" "Go-http-client/1.1" "-"
223.1*.*.* - - [11/Mar/2024:00:01:37 +0800] "GET /weather/baidu HTTP/1.1" 200 350 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app" "-"
116.1*.*.* - - [11/Mar/2024:00:01:39 +0800] "GET /weather/baidu HTTP/1.1" 200 354 "-" "Mozilla/5.0 (Linux; Android 12; PDKM00 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046269 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/37.333332)" "-"
223.7*.*.* - - [11/Mar/2024:00:01:46 +0800] "GET /weather/baidu HTTP/1.1" 200 363 "-" "Mozilla/5.0 (Linux; Android 10; SEA-AL10 Build/HUAWEISEA-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046278 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/27.0)" "-"
182.2*.*.* - - [11/Mar/2024:00:01:50 +0800] "GET /today/list/ HTTP/1.1" 200 885 "-" "okhttp/3.10.0" "-"
221.2*.*.* - - [11/Mar/2024:00:01:55 +0800] "GET /today/list/ HTTP/1.1" 200 885 "-" "okhttp/3.10.0" "-"
223.7*.*.* - - [11/Mar/2024:00:01:55 +0800] "GET /weather/baidu HTTP/1.1" 200 363 "-" "Mozilla/5.0 (Linux; Android 10; SEA-AL10 Build/HUAWEISEA-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046278 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/27.0)" "-"
120.2*.*.* - - [11/Mar/2024:00:01:57 +0800] "GET /weather/baidu HTTP/1.1" 200 350 "-" "Mozilla/5.0 (Linux; Android 10; V2002A Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046247 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/33.0)" "-"

)

至于其他的格式的日志 可以修改 日期匹配规则 参数

Post Author: admin