Как я могу сканировать несколько файлов журналов, чтобы найти, какие из них имеют определенный IP-адрес? - PullRequest
1 голос
/ 12 января 2009

В последнее время на моем сервере было несколько злоумышленников, пробующих вредоносные программы, поэтому я решил несколько «отследить» их, хотя знаю, что они далеко не уйдут.

Теперь у меня есть весь каталог, содержащий журналы сервера, и мне нужен способ поиска по каждому файлу в каталоге и возвращения имени файла, если найдена строка. Поэтому я подумал про себя: что может быть лучше для языка и текстовых операций, чем 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. Я просто собираюсь запустить скрипт из каталога журналов, если вы спрашиваете об изменении каталога на «.»

Mike.

Ответы [ 14 ]

14 голосов
/ 12 января 2009

Можете ли вы использовать grep вместо?

5 голосов
/ 12 января 2009

Чтобы получить все строки с IP, я бы напрямую использовал grep , не нужно показывать список файлов, это простая команда:

grep 12\.211\.23\.200 *

Мне нравится передавать его в другой файл, а затем открывать этот файл в редакторе ...

Если вы настаиваете на желании имен файлов, это также просто

grep -l 12\.211\.23\.200 *

grep доступен во всех Unix // Linux с инструментами GNU или в Windows с использованием одной из многих реализаций (unxutils, cygwin, ... и т. Д.)

3 голосов
/ 12 января 2009

При использовании файлов, найденных через readdir, вам необходимо объединить $dirname с $filname, помните, что вы не chdir 'ввели каталог, в котором находятся эти файлы.

open FH, "<", "$dirname/$filname" or die "Cannot open $filname:$!";

Кстати, почему бы просто не использовать grep -r для рекурсивного поиска по всем подкаталогам в вашей директории log вашей строки?

РЕДАКТИРОВАТЬ: Я вижу ваши правки и две вещи. Во-первых, эта строка:

@files = grep(/\.*$/,readdir(DIR));

Неэффективно, потому что вы ищете ноль или более . символов в конце строки. Так как это ноль или больше, он будет соответствовать всему в каталоге. Если вы пытаетесь исключить файлы, заканчивающиеся на ., попробуйте следующее:

@files = grep(!/\.$/,readdir(DIR));

Обратите внимание на знак ! для отрицания, если вы пытаетесь исключить эти файлы. В противном случае (если вам нужны только эти файлы, а я неправильно понимаю ваши намерения), оставьте !.

В любом случае, если вы получаете сообщение die в строке 10, скорее всего, вы попали в файл с такими правами доступа, что вы не можете его прочитать. Попробуйте ввести имя файла в выходной файл die, чтобы увидеть, в каком файле происходит сбой:

open FILE, "$file" or die "Unable to open file: $file";

Но как и в других ответах, и повторять: Почему бы не использовать grep? Команда unix, а не функция Perl.

2 голосов
/ 12 января 2009

Это позволит получить имена файлов, которые вы ищете в perl, и, вероятно, сделает это намного быстрее, чем запуск и регулярное выражение perl.

@files = `find ~/ServerLogs -name "*.log" | xargs grep -l "<ip address>"`'

Хотя для этого потребуется * nix-совместимая система или Cygwin в Windows.

1 голос
/ 12 января 2009

Кстати, я думал, что добавлю упоминание для File :: Next. Чтобы перебрать все файлы в каталоге (рекурсивно):

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 безопасен для заражения.

1 голос
/ 12 января 2009

Мое первое предложение - вместо этого использовать grep. Правильный инструмент для работы, говорят они ...

Но чтобы ответить на ваш вопрос:

readdir просто возвращает имена файлов из каталога. Вам нужно объединить имя каталога и имя файла вместе.

$path = "$dirname/$filname";
open FH, $path or die ...

Тогда вы должны игнорировать файлы, которые на самом деле являются каталогами, например, "." а также "..". После получения $ path проверьте, является ли это файлом.

if (-f $path) {
    open FH, $path or die ...
    while (<FH>)
1 голос
/ 12 января 2009

Сначала получите список файлов в вашем исходном каталоге:

opendir(DIR, "$dir");
@files = grep(/\.log$/,readdir(DIR));
closedir(DIR);

А затем перебрать эти файлы

foreach $file(@files)
{
  // file processing code
}
0 голосов
/ 13 февраля 2013

Используйте perl из командной строки, как лучший grep

perl -wnl -e '/12.211.23.200/ и печать;' * .log> output.txt

преимущество здесь в том, что вы можете гораздо проще связать логику

perl -wnl -e '(/12.211.23.20[1-11]/ или / denied / i) и print;' * .Log

если вы чувствуете себя странно, вы также можете использовать более продвинутые параметры командной строки для передачи результатов perl one liner в другие liner perl one.

Вам действительно нужно прочитать "Minimal Perl: для людей с UNIX и Linux", потрясающая книга о таких вещах.

0 голосов
/ 20 марта 2009

Я знаю, что слишком поздно для этого обсуждения (наткнулся на него во время поиска сообщений, связанных с grep), но я все равно отвечу:

Точно не указано, являются ли это журналы веб-сервера (Apache, IIS, W3SVC и т. Д.), Но лучшим инструментом для извлечения этих данных является инструмент LogParser от Microsoft. См. Logparser.com для получения дополнительной информации.

LogParser позволит вам писать SQL-подобные операторы для файлов журнала. Это очень гибкий и очень быстрый.

0 голосов
/ 12 января 2009

Сначала используйте 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/;

"." является подстановочным знаком regex, означающим «любой символ». Изменение его на «\.» уменьшит количество ложных срабатываний (на практике вряд ли изменит ваши результаты, но в любом случае это более корректно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...