1

perl 新手,可以使用一些帮助来了解正则表达式以及如何使用它们。我有一个文件名 auth.log,其中包含一堆成功和失败的登录。我有我希望正确的代码来读取文件并逐行读取,现在我只需要弄清楚如何拉出失败的代码并按日期将它们打印到屏幕上。下面是一个登录失败的例子,以及我在文件中读取的代码。我知道正则表达式会查找单词 failed 的匹配项,我只是无法获得语法。

9 月 14 日 07:23:59 icarus sshd [10393]:来自 137.190.220.15 端口 64704 ssh2 的 someUser 的密码失败

9 月 14 日 07:24:04 icarus sshd [10393]:来自 137.190.220.15 端口 64704 ssh2 的 someUser 的密码失败

9 月 14 日 07:30:17 icarus sshd [10523]:接受来自 137.190.19.13 端口 58506 ssh2 的 someUser 的密码

我相信我现在越来越近了,试图在其中启动一个计数变量只是为了吐出文件中有多少失败的密码,当我运行这个脚本时,我得到了大量的数字,最终只是再次以提示结束,我相信这意味着它至少仍在运行整个 auth.log,或者它没有尽头?有任何想法吗?

#!/usr/bin/perl
$count = 0;

open (MYFILE, 'auth.log');
while (my $line = <MYFILE>){
if ($line =~ /Failed password/){
$count++;
}
print $count;
#print "$line\n" if $line =~ /Failed password/; 
#this was a test to make sure it was was getting all the Failed password attempts in              the auth.log.
}
close (MYFILE);

任何帮助都会很棒。

4

3 回答 3

2
use strict;
use warnings;

my $current_date = '';

open ( my $file, 'auth.log') or die 'Could not open auth.log';

while ( <$file> ) {
    next unless my ( $user_id ) = m/\Q: Failed password for \E(\w+)/;
    my ( $date ) = m/^((?:J[au]n|Feb|Ma[ry]|Apr|Jul|Aug|Sep|Oct|Nov|Dec) \s+ \d+)/x;
    if ( $date ne $current_date ) {
        $current_date = $date;
        %failures_for = ();
        print "$current_date\n--- --\n";
    }
    my $time = ++$failures_for{$user_id};
    print "$user_id #$time: $_";
}
print "\n";
close $file;

我还添加了一个想法,即为用户保存失败计数,每天重置。

于 2013-03-14T20:27:23.067 回答
2

这是瑞士军刀的方法。

要查看所有失败:

cat auth.log | perl -ne 'print if /Failed password/'

要查看 9 月的所有故障:

cat auth.log | perl -ne 'print if /Failed password/' | perl -ne 'print if /^Sep/'

查看 'Sep 07 00:00:00' 和 'Oct 18 22:20:00' 之间的所有故障

cat auth.log | perl -ne 'print if /Failed password/' | perl -ane '$date = @F[0..2]; print if q(Sep 07 00:00:00) <= $date && $date <= q(Oct 18 22:20:00)'

要计算它们:

cat auth.log | perl -ne 'print if /Failed password/' | perl -ane '$date = @F[0..2]; print if q(Sep 07 00:00:00) <= $date && $date <= q(Oct 18 22:20:00)' | wc -l

为 SomeRandomUser 找到它们

cat auth.log | perl -ne 'print if /Failed password/' | perl -ne 'print if / for SomeRandomUser /'

我的论点是,学习这种 Perl 风格可以让您以难以提前预料的方式快速地从日志文件中进行自定义提取。一旦你让它们工作,你可以在以后把它们变成一个更强大的程序,如果这为你的公司增加了价值。

附言。我最喜欢的是如何提取文件的第 123 到 456 行?您可以使用 head 和 tail 的组合,例如:

cat file | tail -n +123 | head -334

但这需要两个命令,一些减法和一个可能的栅栏错误。相反,我记住了:

cat file | perl -ne 'print if 123 .. 456'

从 123 打印到文件末尾:

cat file | perl -ne 'print if 123 .. eof'

这在您的情况下可能很有用 - 您可以使用编辑器查看日志您感兴趣的日期的条目在第 1234 到 2345 行,然后执行

cat auth.log | perl -ne 'print if 1234 .. 2345' | perl -ne 'print if /Failed password/'
于 2013-03-14T22:17:29.150 回答
1

像这样的东西应该工作..

#!/usr/bin/perl
open(MYFILE, '<auth.log');
while (my $line = <MYFILE>) {
  print "$line\n" if $line =~ /Failed password/;
}
close(MYFILE);

如果您想花哨并仅提取用户/ IP ..您可以这样做

print "$1 User: $2, IP: $3\n" if $line =~ m/^([A-Za-z]{3}\s+[0-9]{,2}\s+[0-9:]+).*Failed password for ([^ ]+) from ([^ ]+)/;

这种技术在正则表达式中使用反向引用来调用,在 Perl 中,$N(其中 N 是某个数字)对应于每组括号中包含的字符串,从左到右。因此$1对应于日期 ..$2对应于 .. 之后的数据(在这种情况下为任何非空格字符)Failed password for或在您提供的所有日志中将包含someUser.. 同样$3将包含 IP,因为它是第三组括号,捕获字符串后面的任何非空格字符from

于 2013-03-14T20:30:44.287 回答