我有一个服务器日志文件,我正在尝试创建一个PHP页面,该页面汇总了它存储的数据。日志中的每条记录都存储在一个新行中,格式为:
207.3.35.52 -- [2007-04-01 01:24:42] "GET index.php HTTP/1.0" 200 11411 "Mozilla/4.0"
//ip -- [timestamp] "GET url HTTP/1.0" status code bytes "user agent".
我正在尝试编写一个摘要,其中显示:请求总数,文章目录中的请求总数,消耗的总带宽以及最终404错误及其页面的数量。
PHP:
$handle = fopen('logfiles/april.log','r') or die ('File opening failed');
$requestsCount = 0;
while (!feof($handle)) {
$dd = fgets($handle);
$requestsCount++;
$parts = explode('"', $dd);
$statusCode = substr($parts[2], 0, 4);
}
fclose($handle);
此代码打开文件并计算记录数量,分离并在记录中查找状态代码编号。当回显$ statusCode时,它确实显示了正确的信息,显示了日志中的所有状态代码。
接受两个争论以完成404错误的函数:
function requests404($l,$s) {
$r = substr_count($l,$s);
return "Total 404 errors: ".$r."<br />";
}
回应结果:
echo requests404($statusCode, '404');
这个函数不起作用,它只返回0.使用PHP中的txt文件是我最弱的技能,我真的很感激一些帮助,因为我认为我可能会以完全错误的方式去做。感谢。
答案 0 :(得分:2)
$handle = fopen('logfiles/april.log','r') or die ('File opening failed');
$requestsCount = 0;
$num404 = 0;
while (!feof($handle)) {
$dd = fgets($handle);
$requestsCount++;
$parts = explode('"', $dd);
$statusCode = substr($parts[2], 0, 4);
if (hasRequestType($statusCode, '404')) $num404++;
}
echo "Total 404 Requests: " . $num404 . "<br />";
fclose($handle);
function hasRequestType($l,$s) {
return substr_count($l,$s) > 0;
}
答案 1 :(得分:2)
虽然我喜欢在许多方面使用PHP。解析日志并不是其中之一。
相反,我真的建议您考虑使用awk进行所有未来的日志解析工作。
这是一个简单的bash / awk脚本,它以一种易于阅读/易于理解的方式实现您的所有需求:
#!/bin/bash
awk '
BEGIN {
total_requests = 0;
total_requests_articles = 0;
total_404s = 0;
total_bandwidth = 0;
} {
total_requests++;
if ( $8 == "404" ) {
total_404s++;
}
if ( $6 ~ /articles/ ) {
total_requests_articles++;
}
total_bandwidth += $9
} END {
printf "total requests: %i\n", total_requests
printf "total requests for articles: %i\n", total_requests_articles
printf "total 404s: %i\n", total_404s
printf "total bandwidth used: %i\n", total_bandwidth
}' ${1}
将此文件用作演示:
207.3.35.52 -- [2007-04-01 01:24:42] "GET index.php HTTP/1.0" 200 11411 "Mozilla/4.0"
207.3.35.52 -- [2007-04-01 01:24:42] "GET index.php HTTP/1.0" 200 11411 "Mozilla/4.0"
207.3.35.52 -- [2007-04-01 01:24:42] "GET index.php HTTP/1.0" 200 11411 "Mozilla/4.0"
207.3.35.52 -- [2007-04-01 01:24:42] "GET articles/index.php HTTP/1.0" 404 11411 "Mozilla/4.0"
207.3.35.52 -- [2007-04-01 01:24:42] "GET articles/index.php HTTP/1.0" 200 11411 "Mozilla/4.0"
207.3.35.52 -- [2007-04-01 01:24:42] "GET index.php HTTP/1.0" 404 11411 "Mozilla/4.0"
以下是结果:
[root@hacklab5 tmp]# ./apache.bash apache.log
total requests: 6
total requests for articles: 2
total 404s: 2
total bandwidth used: 68466
只是说.. Awk太棒了。而且速度快。并为解析日志量身定制。现在,向大家学习一些好东西;)
干杯 -
答案 2 :(得分:0)
substr_count
将$statusCode
中出现“404”的次数相加,$statusCode
每次只有四个字节“200”(或“304”或“ 404“)一行日志。
因此,只要状态代码不 404,您就会得到零,这是正确的。
您需要在每个输入行上调用requests404
,并总计总和。
实际上使用数组可能会更好:
$totals = array(
200 => 0,
404 => 0,
304 => 0,
);
$requestsCount = 0;
$bytesSent = 0;
$totalBytes = 0;
while (!feof($handle)) {
$dd = fgets($handle);
$requestsCount++;
$parts = explode('"', $dd);
list($statusCode, $bytes) = explode(" ", $parts[2]);
if (!isset($totals[$statusCode]))
$totals[$statusCode] = 0;
$totals[$statusCode]++;
if (200 == $statusCode)
$bytesSent += $bytes;
$totalBytes += $bytes;
}
fclose($handle);
printf("We got $totals[404] 404 errors\n");
在循环结束时,$ totals将保持类似
的内容{
200 => 12345,
404 => 1234,
401 => 22,
304 => 7890,
...
}