2012-11-14 57 views
1

我有一個服務器日誌文件,我正嘗試從中創建彙總其存儲的數據的PHP頁面。日誌中的每條記錄都存儲在一個新的生產線,並在格式:使用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時,它會顯示正確的信息,顯示日誌中的所有狀態碼。

接受兩個arguements以總價404錯誤的函數:

function requests404($l,$s) { 
     $r = substr_count($l,$s); 
     return "Total 404 errors: ".$r."<br />"; 
} 

回聲結果:

echo requests404($statusCode, '404'); 

此功能不起作用,它只是返回0。txt文件工作在PHP中是我最弱的技能,我真的很感謝一些幫助,因爲我認爲我可能會以完全錯誤的方式去解決它。謝謝。

+0

你考慮在每行正則表達式來分析和檢索具體的數據? –

+1

快速檢查,您傳遞給requests404的$ statusCode是否可能僅包含日誌的最後一行? – emartel

+0

我不這麼認爲,因爲當我回顯$ statusCode時,它會顯示所有代碼,並且將arguemnt更改爲'200'並不會使其顯示1爲總和。 – Tom

回答

1
$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; 
} 
+0

這很好地工作。將{}置於IF語句後。我將如何調整它以找出已使用的總字節數的總和? – Tom

0

substr_count將總結的「404」出現的次數內$statusCode,和$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"); 

在循環結束時,$總計將雖然我喜歡使用PHP持有類似

{ 
    200 => 12345, 
    404 => 1234, 
    401 =>  22, 
    304 => 7890, 
    ... 
} 
2

對於很多事情來說。解析日誌並不是其中之一。

相反,我真的希望你看看使用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" 

這裏的結果是什麼樣子:

[[email protected] tmp]# ./apache.bash apache.log 
total requests: 6 
total requests for articles: 2 
total 404s: 2 
total bandwidth used: 68466 

只是說.. AWK是一個wesome。快速燃燒。併爲解析日誌量身打造。現在,你學習AWK一些偉大的好;)

乾杯 -