3

サーバーログファイルがあり、そこから、保存されているデータを要約した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".

私は、リクエストの合計量、articlesディレクトリからのリクエストの合計量、消費された帯域幅の合計、そして最後に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エラーを合計するために2つの引数を受け入れる関数:

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

結果をエコーし​​ます。

echo requests404($statusCode, '404');

この関数は機能せず、0を返すだけです。PHPでtxtファイルを操作することは私の最も弱いスキルであり、完全に間違った方法で行っている可能性があるので、助けていただければ幸いです。ありがとう。

4

3 に答える 3

3
$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;
}
于 2012-11-14T14:32:37.807 に答える
3

私は多くのことにPHPを使用するのが大好きですが、ログの解析はその1つではありません。

代わりに、今後のすべてのログ解析作業に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は素晴らしいです。そして、速く燃えます。また、ログの解析用に調整されています。さて、あなたに素晴らしい善のためのいくつかのawkを学びましょう;)

乾杯 -

于 2012-11-14T14:58:43.077 に答える
0

substr_count$statusCodeは、内の「404」の出現回数を合計し$statusCode、毎回、ログの1行の「200」(または「304」または「404」)の4バイトのみになります。

したがって、ステータスコードが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,
    ...
}
于 2012-11-14T14:32:24.903 に答える