Почему JBoss и Logrotate создают файлы журналов, содержащие символы NUL?
Я настроил Logrotate для ночного вращения журналов JBoss Application Server 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?
3 ответа
У нас была такая же проблема для файла, записываемого log4j. Решением было установить свойство "Append" для 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>
- Создайте сценарий оболочки, который сжимает свернутый файл журнала.
- Установите этот сценарий оболочки в Crontab сервера Unix, чтобы он работал ежедневно. Например, запускается ежедневно в 0:10 утра (почему 0:10 утра? Это дает достаточно времени для log4j, чтобы завершить ролловер, на тот случай, если файлы журналов слишком велики или слишком много файлов журналов. сжать).
- Наконец, убедитесь, что ролловер log4j выполняется в 12:00 (по умолчанию) и задание cron, которое выполняет сценарий оболочки в 0:10.