Как продолжить перенаправление stdout в файл после его перемещения logrotate?

22

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

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

Я также нашел этот пост, в котором была та же проблема, что и у меня, и утверждает, что его можно исправить, используя >>вместо >перенаправления вывод. Я проверил его решение, но оно не сработало для меня. У кого-нибудь есть идеи, как сохранить работу перенаправления?

Mehran
источник
4
Я бы по-прежнему рекомендовал, в вашем случае, использовать «>>» вместо «>», если вы собираетесь записывать в усеченный файл: при открытии «>>» в режиме добавления, он будет искать до конца файла каждый раз пишет. Таким образом, когда вы усекаете файл (переводя его из XXXX байтов в 0 байтов), он будет «искать до конца», поэтому будет знать, что теперь он должен записывать после байта 0. В противном случае он может записывать после байта XXXX, и, таким образом создать разреженный файл с XXXX нулевого байта , прежде чем он (то есть, когда «>», файловым дескриптор может просто вспомнить , где именно в этом файл, и писать оттуда, не понимая Усадку размера файла!)
Оливье Дюлак

Ответы:

25

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

copytruncate Обрезать оригинальный файл журнала на месте после создания копии, вместо перемещения старого файла журнала и, при необходимости, создания нового. Его можно использовать, когда какой-либо программе нельзя сказать, чтобы она закрыла свой файл журнала, и, таким образом, может продолжить запись (добавление) в предыдущий файл журнала навсегда. Обратите внимание, что между копированием файла и его усечением существует очень маленький временной интервал, поэтому некоторые данные журналов могут быть потеряны. Когда эта опция используется, опция создания не будет иметь никакого эффекта, так как старый файл журнала остается на месте

user9517 поддерживает GoFundMonica
источник
2
Возможно, стоит упомянуть: за короткое время, до compressоперации, данные дублируются. Это однажды вызвало у нас проблему, но это было плохо, потому что мы не должны были быть так близко к lvпределу пространства. Кроме того, как указано во manфрагменте, вы можете потерять некоторые данные журнала между операциями копирования и усечения.
Бельмин Фернандес
6

В качестве альтернативы вы также можете:

  • используйте утилиту logger в вашем скрипте вместо конвейера со специальным средством (например, local5), например:

    logger -p local5.info -t myscriptname "this is some log data"

  • Сконфигурируйте syslog, чтобы записать эту возможность в нужный файл журнала, например (rsyslog.conf):

    local5.* /var/log/mylogfile

  • настроить правило logrotate для этого журнала.

tonioc
источник
Это работает, только если у вас есть явные команды вывода, такие как echo. Вывод сторонних инструментов, которые вызываются из скрипта и также выводят что-то, не может быть перенаправлен в логгер таким образом
Даниэль Алдер
4

Другой альтернативой Iain-решения является использование postrotateскрипта для повторного запуска скрипта после ротации. Это делается для большого количества демонов (перезапустите или перезагрузите демон), но не зная вашего сценария, я не знаю, подойдет ли вам это решение или нет (зависит ли ваш сценарий от какого-то состояния, сгенерированного некоторое время назад?).

Содержание /etc/logrotate.d/your-script-name:

/var/log/your-script-name.log {
    # your current logrotate options
    ...
    postrotate
        # this supposing you have the current pid stored
        cat /run/your-script-name.pid | xargs -r kill
        #relaunch it again
        /usr/local/bin/your-script-name
    endscript
}
Карлос Кампдеррос
источник
0

Вы можете направить stdout в «split» (часть coreutils в linux). Он позволяет вам разбивать файл / стандартный ввод на куски в зависимости от размера, количества строк и т. Д. После того, как вы получите его, вы можете при необходимости управлять им с помощью logrotate.

Назар
источник