我在编写日志解析器时遇到问题。我刚开始编写更大的Perl程序/脚本,但是很好地理解bash / ksh,所以我在较小的规模上有一些经验。我为大量的代码道歉,但我不知道我哪里出错了(错误可能会误导,所以我读过)。我已经在这里检查过,PerlMaven和其他一些网站,并且无法让它发挥作用。
我正在尝试将日志文件提供给此解析器,让它按每列拆分日志,并按特定列的实例计数。
在这个解析器中,$statusCode
代表一个成功的连接 - 所以我试图计算使用它成功连接的次数 - 以及有数据传输的成功连接数(如由$sentbyClientBytes > 0
表示。如果连接成功但发送了0个字节,我只想将一个总和增加一个实例(successconnect++
)
其他数据暂时可以丢弃,但我会做一些类似于其他一些列的事情 - 只是使用不同的状态代码反复创建相同类型的函数。
先谢谢Perl大师。你们和你们的知识一起举办互联网。
#!/usr/bin/perl
#V0.1 - testing and initiation
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
my $filename = "/dir/log";
open( my $fh, '<', "/dir/log" ) or die "Cannot open < /root/fall_log";
while ( <$fh> ) {
# wraps whole process from here to end
my $sentcount = 0;
my $successconnect = 0;
# define the counts and variables we're using
my ( $date, $time, $clientIP, $clientPort, $username, $method, $stem,
$query, $statusCode, $SentByServerBytes, $SentByClientBytes,
$servername, $serverport ) = split;
chomp;
## (use $line parameter?)
foreach ( $statusCode ) { # SC 226 is successful action and usually
# indicates download or login
if ( $statusCode == "226" ) {
if ( looks_like_number($SentByClientBytes) ) {
# adding in looks like number because "-" shows up in the
# fields where there are null values
if ( $SentByClientBytes > 0 ) {
$sentcount++ && $successconnect++;
}
else {
$successconnect++;
}
}
# This function counts each successful established connection and
# determines whether bytes were sent - if bytes were sent it
# should register as a count of "one" for successful connection
# and sent count. These counts should be measured and totaled and
# will equal total number of successful downloads and total number
# of successful connections. The numbers should be very close to
# each other as nearly all successful connections will include a
# download.
print $sentcount & $successconnect;
}
}
}
添加我要解析的部分日志(如下)。之后尝试结果的解释:
2016-03-01 06:16:24 192.168.1.10 - - [5475]user USERNAME\admin - 331 - - - 9045
2016-03-01 06:16:25 192.168.1.10 - USERNAME\admin [5476]quit - - 221 - - - 9045
2016-03-01 06:26:25 192.168.1.10 - USERNAME\admin [5475]ssh_disconnect timeout - 421 - - - 9045
2016-03-01 06:26:25 192.168.1.10 - USERNAME\admin [5475]kick - - 421 - - - 9045
2016-03-01 06:26:26 192.168.1.10 - USERNAME\admin [5475]ssh_disconnect timeout - 421 - - - 9045
2016-03-01 06:26:26 192.168.1.10 - USERNAME\admin [5475]kick - - 421 - - - 9045
2016-03-01 06:26:26 192.168.1.10 - USERNAME\admin [5475]quit - - 226 - - - 9045
2016-03-01 06:31:26 192.168.1.10 - - [5516]user USERNAME\admin - 331 - - - 9045
2016-03-01 06:31:27 192.168.1.10 - - [5515]user USERNAME\admin - 226 - - - 9045
2016-03-01 06:31:28 192.168.1.10 - - [5516]user USERNAME\admin - 226 - - - 9045
2016-03-01 06:31:28 192.168.1.10 - - [5515]user USERNAME\admin - 226 - - - 9045
2016-03-01 06:31:28 192.168.1.10 - USERNAME\admin [5516]quit - - 221 - - - 9045
2016-03-01 06:41:29 192.168.1.10 - USERNAME\admin [5515]ssh_disconnect timeout - 421 - - - 9045
2016-03-01 06:41:29 192.168.1.10 - USERNAME\admin [5515]kick - - 421 - - - 9045
2016-03-01 06:41:30 192.168.1.10 - USERNAME\admin [5515]quit - - 221 - - - 9045
2016-03-01 06:46:30 192.168.1.10 - - [5545]user USERNAME\admin - 331 - - - 9045
2016-03-01 06:46:31 192.168.1.10 - - [5544]user USERNAME\admin - 331 - - - 9045
2016-03-01 06:46:31 192.168.1.10 - - [5545]user USERNAME\admin - 331 - - - 9045
2016-03-01 06:46:31 192.168.1.10 - - [5544]user USERNAME\admin - 331 - - - 9045
2016-03-01 06:46:32 192.168.1.10 - USERNAME\admin [5545]quit - - 221 - - - 9045
2016-03-01 06:56:32 192.168.1.10 - USERNAME\admin [5544]ssh_disconnect timeout - 421 - - - 9045
2016-03-01 06:56:32 192.168.1.10 - USERNAME\admin [5544]kick - - 421 - - - 9045
2016-03-01 06:56:33 192.168.1.10 - USERNAME\admin [5544]ssh_disconnect timeout - 421 - - - 9045
2016-03-01 06:56:33 192.168.1.10 - USERNAME\admin [5544]kick - - 421 - - - 9045
2016-03-01 06:56:33 192.168.1.10 - USERNAME\admin [5544]quit - - 221 - - - 9045
2016-03-01 07:00:01 192.168.1.10 - - [5565]user USERNAME\admin - 331 - - - 9045
2016-03-01 07:00:02 192.168.1.10 - - [5565]user USERNAME\admin - 331 - - - 9045
2016-03-01 07:00:03 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/5256570.pdf - 226 - 50935 - 9045
2016-03-01 07:00:04 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256534.pdf - 226 - 52404 - 9045
2016-03-01 07:00:05 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256671.pdf - 226 - 50336 - 9045
2016-03-01 07:00:06 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256565.pdf - 226 - 50858 - 9045
2016-03-01 07:00:06 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256634.pdf - 226 - 51039 - 9045
2016-03-01 07:00:07 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/5256536.pdf - 226 - 51657 - 9045
2016-03-01 07:00:07 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256668.pdf - 226 - 51219 - 9045
2016-03-01 07:00:08 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256666.pdf - 226 - 50397 - 9045
2016-03-01 07:00:09 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256641.pdf - 226 - 50652 - 9045
2016-03-01 07:00:09 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256648.pdf - 226 - 51529 - 9045
2016-03-01 07:00:10 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256525.pdf - 226 - 50913 - 9045
2016-03-01 06:46:30 192.168.1.10 - - [5545]USERNAME\Admin - 226 - - - 9045
2016-03-01 06:46:31 192.168.1.10 - - [5544]USERNAME\Admin -226 - - - 9045
2016-03-01 06:46:31 192.168.1.10 - - [5545]USERNAME\Admin - 331 - - - 9045
2016-03-01 06:46:31 192.168.1.10 - - [5544]USERNAME\Admin - 331 - - - 9045
这应检查第9列($statuscode)
包含226(成功连接)的所有实例,并将其与第10列($SentByServerBytes)
进行比较,以查看是否实际发送了数据。如果第10列大于0,则将一个“实例”添加到$successconnect
,将一个实例添加到$sentcount
。如果($SentByServerBytes)
列为零(表示连接成功但未传输任何数据(例如 - 日志文件中的第7,9,10和11行),则将一个实例添加到$successconnect
但是不是$sentcount
的一个实例。
为了清晰起见重新措辞:
如果$statuscode
为226,则始终将一个实例添加到$ successconnect。仅当($SentByServerBytes)
大于0时,才将一个实例添加到$sentcount
根据这个日志,我应该结束
$successconnect
= 17次成功连接
$sentcount
=已发送11个成功文件
我现在是gettig
[root@localhost ~]# ./logcounter1.pl
Use of uninitialized value in string eq at ./logcounter1.pl line 22, <$fh> line 998.
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111[root@localhost ~]
再次感谢大家的帮助!我很难过,但你们总是非常有帮助!!!!!
答案 0 :(得分:6)
如果您可以提供输入数据样本和所需的输出,那将非常有用。因为它是你的程序中有很多多余的代码
其他人发现的错误并不是真正的问题。 (将foreach
与单个值一起使用将只执行一次循环,并且使用与字符串的数字比较将首先将字符串转换为整数。)但它确实表明您对所拥有的内容缺乏了解写入
您正尝试将每行的第九个字段提取为$statusCode
的值,以及特定错误
在数字eq(==)
中使用未初始化的值
几乎可以肯定,因为日志文件中的一行包含的字段少于9个,因此变量设置为undef
每次从文件中读取一行时,您还会打印$sentcount
$successconnect
的按位和。这是一个非常奇怪的打印值,我想你想在读完整个文件后打印摘要
这是重写你的程序,做我认为你想要的
#!/usr/bin/perl
#V0.1 - testing and initiation
use strict;
use warnings 'all';
use Scalar::Util 'looks_like_number';
my $filename = '/dir/log';
open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!};
my $sent_count = 0;
my $success_connect = 0;
while ( <$fh> ) {
my @fields = split;
next unless @fields >= 9;
my ( $status_code, $sent_by_client_bytes) = @fields[8,10];
if ( defined $status_code and $status_code eq '226' ) {
++$success_connect;
if ( defined $sent_by_client_bytes
and looks_like_number($sent_by_client_bytes)
and $sent_by_client_bytes > 0 ) {
++$sent_count;
}
}
}
print qq{\$success_connect = $success_connect\n};
print qq{\$sent_count = $sent_count\n};
答案 1 :(得分:0)
$statusCode
不是数组引用,而是标量字符串,所以做foreach ($statusCode)
没有任何意义。
在访问之前,您还应验证$statusCode
是否为defined
。如果不是,则split
的结果不正确,或者您的输入行没有您期望的格式。
一些脚注:
==
用于数字,使用eq
表示字符串:
if ( $statusCode eq "226") {
或
if ( $statusCode == 226) {
Perl perlop页面提供了更多信息。
此外,不要依赖$sentcount++ && $successconnect++;
等条件的副作用
而是将它作为两个单独的命令:$sentcount++; $successconnect++;
此外,您在第二个;
之后错过了$successconnect++
。那说,以下......
if ($SentByClientBytes > 0) {
$sentcount++ && $successconnect++;
} else {
$successconnect++
}
应该简化为:
$successconnect++;
if ($SentByClientBytes > 0) { $sentcount++; }
答案 2 :(得分:0)
您的代码:if ( $statusCode == "226" ) {
==用于比较数字,但&#34; 226&#34;是一个字符串,因为你加倍引用它。使用其中一个:
my $procname="SUBROUTINENAME";
if (! defined($statusCode))
{
print "$procname ERROR: statusCode not defined\n";
}
elsif ($statusCode eq "226" ) {...
}
或
my $procname="SUBROUTINENAME";
if (! defined($statusCode))
{
print "$procname ERROR: statusCode not defined\n";
}
elsif ($statusCode == 226 ) {...
}
我喜欢将过程名称放在错误消息中。 一个常见的错误,朋友。