65.9K
CodeProject 正在变化。 阅读更多。
Home

自制 Apache 日志分析器来计算命中数。

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.60/5 (2投票s)

2012 年 1 月 4 日

CPOL

3分钟阅读

viewsIcon

19406

基于 Apache 日志文件,报告来自本地主机和其他地方的访问次数的方法。

引言

有很多用于 Apache 日志文件的日志分析器,但总有一些特殊情况是它们都无法处理的,或者无法按照你希望的方式处理。

这是一个简单的 Perl 脚本,允许你根据访问者的 IP 地址来统计他们。

背景

在这种情况下,我需要统计来自 "localhost"(即 "127.0.0.1")的访问次数,以及来自其他地方的访问次数。我展示并解释了执行此操作的脚本。

使用代码

Apache 生成的日志文件有很多行,所有行都以类似的内容开头

127.0.0.1 - - [10/Apr/2007:10:39:11 +0300] ...
127.0.0.1 - - [10/Apr/2007:10:39:11 +0300] ...
139.12.0.2 - - [10/Apr/2007:10:40:54 +0300] ...
217.1.20.22 - - [10/Apr/2007:10:40:54 +0300] ...

首先是 IP 地址,然后是一个空格,一个破折号 (-),然后是更多的数据。

脚本看起来像这样

#!/usr/bin/perl
use strict;
use warnings;

my $file = shift or die "Usage: $0 FILE\n";
open my $fh, '<', $file or die "Could not open '$file': $!";

my $local  = 0;
my $remote = 0;
while (my $line = <$fh>) {
    my $length = index ($line, " ");
    my $ip = substr($line, 0, $length);
    if ($ip eq "127.0.0.1") {
        $local++;
    } else {
        $remote++;
    }
}

print "Local: $local Remote: $remote\n";

将其保存为 "analyzer.pl" 并以 "perl analyzer.pl" 的方式运行它。

让我们来看看它。

第一行被称为 shebang。 只有当你希望将脚本变成 Unix/Linux 可执行文件时才需要它。

use strict;
use warnings;

这些非常类似于其他语言中的编译器标志。 它们帮助你避免常见的编程错误。 我称它们为安全网。 如果没有它们,我不会编写任何 Perl 脚本。

my $file = shift or die "Usage: $0 FILE\n";   

最好分成两部分来解释

my $file = shift

将从 @ARGV (保存命令行参数的数组) 中获取第一个元素,并将其移到 $file 变量中,该变量刚刚使用 "my" 关键字声明。

然后是 "or" 逻辑运算符。

如果用户提供了文件名,则 "or" 的左侧将计算为真值,并且脚本继续执行。如果用户没有提供命令行参数,则 "or" 的右侧将启动,Perl 将停止执行并显示使用消息。

Usage: analyze.pl FILENAME
open my $fh, '<', $file or die "Could not open '$file': $!";  

以上是一个类似的逻辑表达式。 左侧打开 $file 进行读取,并将文件句柄放入新的 $fh 变量中。 如果成功,open 返回 true,脚本继续执行。 如果失败,open 返回 false,右侧启动。 Perl 显示错误消息并停止执行。

然后我们声明两个标量变量,并将 0 分配给它们中的每一个。 我们将它们用作计数器,用于计算以 "127.0.0.1" 开头的行数和其他行数。

while 循环逐行读取文件,并为每一行执行该块的内容。 当我们完成读取文件时,while 将停止。

while (my $line = <$fh>) {
}

index() 函数获取一个字符串和一个子字符串,并返回子字符串(第二个参数)在第一个字符串中的位置。 它使用基于 0 的索引,并且我们正在寻找一个空格。 结果数字将是当前行中 IP 地址的长度。

my $length = index ($line, " "); 

substr() 获取一个字符串、一个索引(偏移量)和一个长度。 它返回位于特定位置的子字符串。 在我们的例子中,这恰好是当前行的 IP 地址。

my $ip = substr($line, 0, $length);  

唯一剩下的事情是检查这是否是 "localhost" 并递增相应的计数器。

if ($ip eq "127.0.0.1") {
    $local++;
} else {
    $remote++;
}

循环完成后,我们打印结果

print "Local: $local Remote: $remote\n"; 

就这样。现在你可以使用这个脚本,甚至可以根据说明改进它。请参阅下一篇文章以获取关于所有访问的 完整源代码分析

© . All rights reserved.