2009-02-10 6 views
4

Я недавно придумал ситуацию, когда мне нужно обрезать некоторые довольно большие файлы журналов, когда они вырастут за определенный размер. Все, кроме последних 1000 строк в каждом файле, удаляются, работа выполняется каждые полчаса cron. Мое решение состояло в том, чтобы просто запустить список файлов, проверить размер и обрезать, если необходимо.Как я могу обрезать файлы журналов с помощью Perl?

for $file (@fileList) { 
    if (((-s $file)/(1024 * 1024)) > $CSize) { 
     open FH, "$file" or die "Cannot open ${file}: $!\n"; 
     $lineNo = 0; 
     my @tLines; 

     while(<FH>) { 
     push @tLines, $_; 
     shift @tLines if ++$lineNo < CLLimit; 
     } 
     close FH; 

     open FH, ">$file" or die "Cannot write to ${file}: $!\n"; 
     print FH @tLines; 
     close FH; 
} 

Это работает в текущей форме, но есть много накладных расходов для больших лог-файлов (особенно те, с 100_000 + линиями) из-за необходимости читать в каждой строке и переложить в случае необходимости.

Можно ли каким-либо образом прочесть только часть файла, например. в этом случае я хочу иметь доступ только к последним строкам «CLLimit». Поскольку сценарий развертывается в системе, которая увидела лучшие дни (думаю, Celeron 700 МГц с 64 МБ ОЗУ), я ищу более быструю альтернативу с использованием Perl.

ответ

8

Я понимаю, что вы хотите использовать Perl, но если это UNIX-система, почему бы не использовать утилиту «tail» для выполнения обрезки? Вы можете сделать это в BASH с очень простым скриптом:

if [ `stat -f "%z" "$file"` -gt "$MAX_FILE_SIZE" ]; then 
    tail -1000 $file > $file.tmp 
    #copy and then rm to avoid inode problems 
    cp $file.tmp $file 
    rm $file.tmp 
fi 

Это, как говорится, вы, вероятно, найти this post очень полезно, если вы установите на использование Perl для этого.

+0

Спасибо за пример bash, у меня есть что-то похожее на это для задачи, но я в процессе преобразования всех моих скриптов bash в Perl и поэтому нуждался в некоторых рекомендациях. Учебник Perl Monks выглядит многообещающим, я посмотрю на него позже. – aks

+0

Даже с системой unix вы можете получить хвост для других ОС. :) –

4

Оцените среднюю длину строки в журнале - назовите ее N байтами.

Ищите назад с конца файла на 1000 * 1.10 * N (10% -ный запас для ошибки в коэффициенте 1.10). Прочитайте оттуда, сохранив только самые последние 1000 строк.


Был ли задан вопрос - какую функцию или модуль?

Встроенная функция seek выглядит как инструмент для использования?

+0

Я действительно думал о чем-то подобном, но с моими довольно ограниченными знаниями о Perl. Я бы не знал, какие модули использовать для выполнения поставленной задачи. Напр. какую функцию я бы использовал, чтобы искать назад в файле в Perl? – aks

4

Рассмотрите возможность использования утилиты logrotate; он включен в большинство современных дистрибутивов Linux. Связанный инструмент для систем BSD называется newsyslog. Эти инструменты разработаны более или менее по назначению: он атомарно перемещает лог-файл на место, создает новый файл (с тем же именем, что и раньше) для хранения новых записей журнала, инструктирует программу, генерирующую сообщения, использовать новый файл, а затем (необязательно) сжимает старый файл. Вы можете настроить количество оборотных журналов. Вот потенциальный учебник: http://www.debian-administration.org/articles/117

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

+0

Я решил эту проблему раньше, и я согласен с вами в управлении кэшированием сообщений со стороны предложения. Если вы не используете интерфейс syslog, при перемещении файла будут возникать странные вещи. –

Смежные вопросы