Назад | Перейти на главную страницу

Почему JBoss и Logrotate создают файлы журнала, заполненные символами NUL?

Я настроил Logrotate для еженощной ротации журналов сервера приложений JBoss 4.2.2.GA. После того, как файлы журнала были повернуты и JBoss снова начнет писать в них, новые файлы журнала начинаются с того же количества символов NUL, сколько было символов в предыдущем файле журнала, за которым следуют новые сообщения журнала. Например, если размер файла JBoss server.log составляет 5000 байтов, то после ротации новый файл server.log будет начинаться с 5000 символов NUL. По прошествии нескольких дней server.log начинается с символов NUL, эквивалентных символам всех файлов журнала за предыдущие дни вместе взятых. Похоже, что JBoss запоминает свою позицию в файле журнала и продолжает работу с того места, где он остановился в усеченном файле. Вот моя конфигурация logrotate для JBoss:

/apps/jboss-4.2.2.GA/server/default/log/*log {
    daily
    rotate 30
    compress
    notifempty
    copytruncate
    missingok
    nocreate
}

Я не могу перезапускать JBoss каждую ночь, потому что это было бы слишком долго. Я также не могу использовать log4j DailyRollingFileAppender, поскольку он не удаляет старые файлы журналов. Кто-нибудь получил, что logrotate правильно работает с JBoss?

У нас была такая же проблема для файла, записываемого log4j. Решением было установить для свойства «Добавить» для FileAppender значение «true». После этого изменения мы не наблюдали этой проблемы с файлами, имеющими NUL при вращении внешней программой, например logrotate.

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

Но нельзя указать Log4j повторно открывать свои файлы журналов, поэтому я вижу, что вы используете copytruncate вместо этого копировать файлы - проблема в том, что Log4j использует буферизованные средства записи, которые отслеживают текущую позицию записываемого файла, и когда вы усекаете файл журнала, log4j продолжает писать с того места, где он прекратил запись, до усечения. В зависимости от реализации вашей файловой системы это должно создавать «файлы с дырами» - т.е. символы NULL, которые вы видите там, на самом деле не существуют - размер файла на самом деле равен фактическим данным, а символ NULL - это то, как ваше средство просмотра представляет отверстие. С другой стороны, некоторые файловые системы не поддерживают дыры и действительно заполняют файл символами NULL, когда Log4j возобновляет запись.

Я предлагаю - не используйте logrotate, найдите способ повернуть файлы в Log4j с помощью RollingFileAppender (который поддерживает удаление старых файлов) или с помощью DailyRollingFileAppender и cronjob, который удаляет старые файлы извне (так как это должно было быть сделано ).

Это прекрасно работает. Подводя итог тому, что предложил @Guss:

1. Откройте свой «log4j.xml» и добавьте следующий аппендер (я использовал класс DailyRollingAppender и настроил его на ежедневное обновление):

* ПРИМЕЧАНИЕ. Частота ролловеров зависит от DatePattern. Видеть: http://www.codejava.net/coding/configure-log4j-for-creating-daily-rolling-log-files

<appender name="RollingAppender" class="org.apache.log4j.DailyRollingFileAppender">
       <param name="File" value="/logging_directory_path_here/server1.log" />
       <param name="DatePattern" value="'.'yyyy-MM-dd" />
       <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="[%p] %d %c %M - %m%n"/>          
       </layout>
    </appender>

    <root>
            <priority value="info" />
            <appender-ref ref="RollingAppender" />
    </root>
  1. Создайте сценарий оболочки, который сжимает развернутый файл журнала.
  2. Установите этот сценарий оболочки в Crontab сервера Unix, чтобы он запускался ежедневно. например Запускается ежедневно в 12:10 (почему в 12:10? Это дает достаточно времени для log4j, чтобы завершить ролловер, на всякий случай, если файл (ы) журнала слишком большой или слишком много файлов журнала для компресс).
  3. Наконец, убедитесь, что log4j Rollover запускается в 12:00 (по умолчанию), а задание cron, которое выполняет сценарий оболочки, в 12:10.