48

У меня есть программа для Linux, которая может записывать информацию в stdout и stderr.

У меня есть сценарий оболочки, который перенаправляет этот вывод в файл в /var/log . (Через >> и 2>&1 )

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

Я видел несколько ответов, в которых рассказывается о программе logrotate , которая звучит хорошо, но, похоже, они также сосредоточены на программах, которые генерируют файлы журнала внутри и обрабатывают сигналы HUP. Есть ли способ сделать это с помощью основного сценария перенаправления вывода?

9 ответов9

35

В качестве альтернативы вы могли бы направить вывод через инструменты, предназначенные для основной цели - поддерживать наборы журнальных файлов с ограниченным размером, автоматически вращаемыми, такие как:

Инструменты для последующей обработки multilog файлов журнала в формате multilog включают, среди прочего:

дальнейшее чтение

15

инструмент rotatelogs , поставляемый с Apache (в папке bin) (см. docs), принимает входные данные из stdin и вращает журнал через некоторое определенное время

14

Если у вас есть возможность перейти к одному из стандартных потоков журналов (syslog, daemon, cron, user, security, mail и т.д.), Вы можете вместо этого использовать команду logger и канал к ней.

echo "Hello." | logger -p daemon.info

В противном случае вам может быть лучше передать записанное содержимое в пользовательскую программу или сценарий для его обработки или посмотреть на настройку конфигурации logrotate .

РЕДАКТИРОВАТЬ: JdeBP ответ, кажется, есть то, что вы можете искать.

14

У меня была похожая проблема, и я изначально отказывался от logrotate, но оказалось, что logrotate действительно может это сделать, ключевая директива - copytruncate . По какой-то причине этот термин не встречается ни в одном из поисковиков, которые я использовал, поэтому я добавляю этот ответ, чтобы уточнить, как именно его использовать в данном случае.

Хитрость в том, что это работает, только если перенаправление выполняется с помощью « >> » (добавление) вместо « > » (создание).

Файл конфигурации (truncate.cfg):

/tmp/temp.log {
    size 10M
    copytruncate
    rotate 4
    maxage 100
}

Тестовая программа (никогда не сдается файл). Вы можете наблюдать за тем, как он заполняет диск, и хотя удаление файла журнала будет работать, на самом деле оно не освободит место на диске:

cat /dev/urandom >> /tmp/temp.log

Запуск журнала поворота:

logrotate truncate.cfg
3

Мне нравится multilog для моего варианта использования, но мой сценарий использования настолько тривиален / прост, что не очень просто изложен в документах / примерах, которые я нашел. Вот простой пример поворота мультилога:

mkdir /tmp/myapp
./myapp | multilog t s10000 n5 '!tai64nlocal' /tmp/myapp 2>&1

Некоторые заметки:

  • этот дамп записывает в этот каталог /tmp /myapp /
  • s10000 представляет 10 000 байтов *
  • N5 представляет 5 файлов.* «Текущий» журнал считается одним из файлов, поэтому он включает в себя 4 старых журнала + «текущий»
  • это основано на примерах, предоставленных Франсуа Босолеем по адресу: http://blog.teksol.info/pages/daemontools/best-practices
  • Я не понимаю многие варианты - я отсылаю вас к различной документации, чтобы расширить это ...
  • Документы предупреждают, что: "Note that running processor may block any program feeding input to multilog." где «процессор» - это '!tai64nlocal' часть команды

* Для многих приложений это плохой выбор для долгосрочного использования. Они позволяют наблюдать за процессом заполнения и вращения журналов быстрее, чем это делают большие журналы.

Наконец, не забудьте nohup, если требуется! С nohup вам не нужны 2>&1 (здесь s = 10e6 и n = 30):

mkdir -p /tmp/myapp
nohup ./myapp | multilog t s10000000 n30 '!tai64nlocal' /tmp/myapp &

Эта команда должна начать вас.

3

Используйте split, это часть coreutils. Он может взять stdin и разбить его на куски (в зависимости от размера чанка, количества строк и т.д.).

Пример:

app | split --bytes 1G - /var/logs/put-prefix-here

Примечание. Тире (-) указывает "split" использовать stdin вместо файла.

3

Так есть ли способ заставить logrotate работать с перенаправленным stdout текущего процесса?

Да! Ознакомьтесь с директивой "copytruncate", предлагаемой logrotate. Указание, которое инструктирует logrotate справиться с этой самой ситуацией: простая программа, которая сохраняет свой файл журнала открытым на неопределенное время.

Одно предупреждение может или не может быть проблемой в вашей ситуации:

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

Как ни странно, я видел некоторые источники журналов "реального мира", которые поощряют пользователей применять эту директиву. Там какое - то обсуждение этого варианта здесь.

1

Я просто хотел добавить к комментарию Сэма Хендли выше:

Хитрость в том, что это работает, только если перенаправление выполняется с помощью >> (append) вместо > (create).

Я столкнулся с той же проблемой, когда исходный файл просто продолжает расти, если вы используете > (создать), но если вы используете >> (добавить), Logrotate copytruncate работает красиво и, как и ожидалось. Исходный файл возвращается к нулю байтов, и программа продолжает запись.

Перенаправьте STDOUT и STDERR во вращающийся лог-файл:

  1. some-program.sh >> /tmp/output.txt 2>&1 &
  2. Создайте файл конфигурации logrotate в /etc/logrotate.d называется любым, output_roll в моем случае.

    Пример конфигурации для моего случая:

    /tmp/output.txt {
        notifempty
        missingok
        size 1G
        copytruncate
        start 0
        rotate 15
        compress
    }
    
  3. Настройте свою работу cron в /etc/crontab

    *  *  *  *  * root /usr/sbin/logrotate /etc/logrotate.d/output_roll
    

    Это будет проверять файл каждую минуту. Вы можете настроить в соответствии с вашими потребностями.

  4. Начни это:

    $> service crond restart
    
  5. это оно

Примечание: у меня также была проблема с SELinux, установленным на SELINUX=enforcing поэтому я установил его на SELINUX=disabled .

1

Я написал logrotee в эти выходные. Я бы не стал, если бы прочитал замечательный ответ @ JdeBP и multilog .

Я сосредоточился на том, чтобы он был легким и имел возможность bzip2 выводить его как:

verbosecommand | logrotee \
  --compress "bzip2 {}" --compress-suffix .bz2 \
  /var/log/verbosecommand.log

Однако многое еще предстоит сделать и проверить.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .