最近有一些攻击者在我的服务器上尝试恶意攻击,所以我决定稍微“跟踪”它们,即使我知道它们不会走得太远。
现在,我有一个包含服务器日志的整个目录,我需要一种方法来搜索目录中的每个文件,并在找到字符串时返回文件名。所以我想,对于文本和文本来说,用什么语言更好?文件操作比Perl?所以我的朋友正在帮助我使用脚本来扫描某个IP的所有文件,并返回包含IP的文件名,这样我就不必手动搜索每个日志的攻击者了。 (我有数百人)
#!/usr/bin/perl
$dir = ".";
opendir(DIR, "$dir");
@files = grep(/\.*$/,readdir(DIR));
closedir(DIR);
foreach $file(@files) {
open FILE, "$file" or die "Unable to open files";
while(<FILE>) {
print if /12.211.23.200/;
}
}
虽然它给我目录读取错误。非常感谢任何帮助。
编辑:代码编辑,仍然说权限被拒绝无法打开第10行的目录。如果您质疑目录更改为“。”,我将从日志目录中运行脚本。麦克
答案 0 :(得分:14)
您可以改用grep吗?
答案 1 :(得分:5)
要获得IP的所有行,我会直接使用 grep ,不需要显示文件列表,这是一个简单的命令:
grep 12\.211\.23\.200 *
我喜欢将它传播到另一个文件,然后在编辑器中打开该文件......
如果你坚持想要文件名,那也很容易
grep -l 12\.211\.23\.200 *
grep可用于所有Unix //使用GNU工具的Linux,或使用众多实现之一(unxutils,cygwin等等)在Windows上使用
答案 2 :(得分:3)
使用通过$dirname
找到的文件时,您必须将$filname
与readdir
连接起来,请记住您没有chdir
加入这些文件所在的目录。< / p>
open FH, "<", "$dirname/$filname" or die "Cannot open $filname:$!";
顺便说一句,为什么不使用grep -r
以递归方式搜索日志目录下的所有子目录作为字符串?
编辑:我看到了您的修改,还有两件事。首先,这一行:
@files = grep(/\.*$/,readdir(DIR));
无效,因为您在字符串末尾搜索零个或多个.
个字符。因为它是零或更多,它将匹配目录中的所有内容。如果您尝试排除以.
结尾的文件,请尝试以下操作:
@files = grep(!/\.$/,readdir(DIR));
如果您尝试排除这些文件,请注意!
符号否定。否则(如果你只想要那些文件并且我误解了你的意图),请离开!
。
在任何情况下,如果您在第10行收到die
消息,则很可能是您遇到的文件具有无法读取的权限。尝试将文件名放在die输出中,这样你就可以看到它失败的文件:
open FILE, "$file" or die "Unable to open file: $file";
但与其他答案一样,并重申:为什么不使用grep? unix命令,而不是Perl函数。
答案 3 :(得分:2)
这将获得你在perl中寻找的文件名,并且可能比运行和执行perl正则表达式要快得多。
@files = `find ~/ServerLogs -name "*.log" | xargs grep -l "<ip address>"`'
虽然这需要符合* nix标准的系统,或Windows上的Cygwin。
答案 4 :(得分:1)
首先获取源目录中的文件列表:
opendir(DIR, "$dir");
@files = grep(/\.log$/,readdir(DIR));
closedir(DIR);
然后循环浏览这些文件
foreach $file(@files)
{
// file processing code
}
答案 5 :(得分:1)
我的第一个建议是使用grep代替。他们说这是工作的正确工具......
但要回答你的问题:
readdir只返回目录中的文件名。您需要将目录名和文件名连接在一起。
$path = "$dirname/$filname";
open FH, $path or die ...
然后你应该忽略实际上是目录的文件,例如“。”和“......”。获取$ path后,检查它是否是文件。
if (-f $path) {
open FH, $path or die ...
while (<FH>)
答案 6 :(得分:1)
use Path::Class; # always useful.
use File::Next;
my $files = File::Next::files( dir(qw/path to files/) ); # look in path/to/files
while( defined ( my $file = $files->() ) ){
$file = file( $file );
say "Examining $file";
say "found foo" if $file->slurp =~ /foo/;
}
File :: Next是污点安全的。
答案 7 :(得分:0)
〜不会在Perl中自动扩展。
opendir my $fh, '~/' or die("Doin It Wrong"); # Doing It Wrong.
opendir my $fh, glob('~/') and die( "Thats right!" );
答案 8 :(得分:0)
另外,如果必须使用readdir()
,请务必保护表达式:
while (defined(my $filename = readdir(DH))) {
...
}
如果你没有进行defined()
测试,如果找到一个名为'0'的文件,循环将终止。
答案 9 :(得分:0)
您是否在CPAN上查看了日志解析器?我用'log parse'搜索了它,它产生了超过200次点击。有些(可能很多)不相关 - 有些可能是。这部分取决于您使用的Web服务器。
答案 10 :(得分:0)
我读到这个吗?你的第10行给出了错误
open FILE, "$file" or die "Unable to open files";
根据第6行,你想要阅读的$文件
@files = grep(/\.*$/,readdir(DIR));
是以零点或多点结尾的文件。这是你真正想要的吗?这基本上匹配目录中的每个文件,包括“。”和“......”。也许你没有足够的权限打开父目录进行阅读?
编辑:如果您只想阅读所有文件(包括隐藏文件),您可能需要使用以下内容:
opendir(DIR, ".");
@files = readdir(DIR);
closedir(DIR);
foreach $file (@files) {
if ($file ne "." and $file ne "..") {
open FILE, "$file" or die "cannot open $file\n";
# do stuff with FILE
}
}
请注意,这不会处理子目录。
答案 11 :(得分:0)
我知道我在这次讨论中已经迟到了(在搜索grep相关帖子时遇到了它)但我还是会回答:
如果这些是Web服务器日志(Apache,IIS,W3SVC等),则没有明确说明,但是用于挖掘数据的最佳工具是Microsoft的LogParser工具。有关详细信息,请参阅logparser.com。
LogParser允许您针对日志文件编写类似SQL的语句。它非常灵活,速度非常快。
答案 12 :(得分:0)
从命令行使用perl,就像更好的grep
这里的好处是你可以更容易地链接逻辑
如果您感觉很古怪,您还可以使用更高级的命令行选项将perl one liner结果提供给其他perl one衬里。
你真的需要阅读“Minimal Perl:For UNIX and Linux People”,这本书非常棒。
答案 13 :(得分:-1)
首先,使用grep
。
但如果你不想,这里有两个小改进,你可以做到我还没有看到提到:
1)改变:
@files = grep(/\.*$/,readdir(DIR));
到
@files = grep({ !-d "$dir/$_" } readdir(DIR));
通过这种方式,您不仅可以排除“。”和“..”以及服务器日志目录中可能存在的任何其他子目录(否则open
下游会阻塞它们。)
2)改变:
print if /12.211.23.200/;
到
print if /12\.211\.23\.200/;
“.
”是一个正则表达式的通配符,意思是“任何字符”。将其更改为“\.
”将减少误报的数量(在实践中不太可能改变您的结果,但无论如何它都更正确。)