Вопрос или проблема
Я использую logrotate на RHEL 9 для ротации логов доступа Apache 2.4 (на самом деле IBM HTTP Server), работающего от имени root.
Конфигурация, которую я использую, представляет собой серию следующего для каждого файла access.log:
<HTTPServer path>/logs/access.log {
compress
dateext
maxage 60
rotate 99
daily
notifempty
missingok
postrotate
<HTTPServer path>/bin/apachectl restart
/bin/sleep 10|/bin/true
endscript
}
Однако после ротации (и действия postrotate) процесс apache, похоже, продолжает записывать в предыдущий файл <HTTPServer path>/logs/access-<prev data>.log
(честно говоря, это inode файла), который теперь удален из-за действия компрессии.
Процесс apache начинает снова записывать в оригинальный файл <HTTPServer path>/logs/access.log
только при выполнении <HTTPServer path>/bin/apachectl restart
из командной строки.
Я пробовал все возможные комбинации (например, delaycompress
, объединение всех файлов доступа в одну конфигурацию и установка sharedscripts
и т.д.), чтобы решить эту проблему, кроме copytruncate, который я хотел бы избежать.
Ответ или решение
Почему Apache 2.4 продолжает записывать в старый файл лога после ротации?
В процессе ротации логов с использованием logrotate
на системе RHEL 9, вы столкнулись с проблемой, когда Apache (IBM HTTP Server в вашем случае) продолжает записывать данные в старый файл лога, несмотря на выполнение команды перезапуска в секции postrotate
. Давайте подробно рассмотрим, что может вызывать эту проблему, и как ее можно решить.
Причины проблемы
-
Дескрипторы файлов: При ротации логов Apache продолжает работать с дескриптором файла, который был открыт до ротации. Если ротация происходит, но процесс Apache не закрывает файл, он продолжает писать в старый файл, сохраняя его дескриптор. Даже если файл был удален, он всё равно остается доступным процессу до тех пор, пока он не будет завершен.
-
Команда перезапуска: Команда
apachectl restart
должна завершить текущие процессы Apache и перезапустить их. Однако, если процессы не завершаются должным образом или происходит какая-либо ошибка, система может продолжать записывать в старый файл. -
Отсутствие конфигурации: Некоторые параметры в конфигурации
logrotate
, такие какdelaycompress
, могут быть неуместны в данном случае. Параметрdelaycompress
позволяет отложить сжатие на один цикл ротации, что может быть причиной, по которой Apache продолжает записывать в старый лог.
Решения и рекомендации
-
Использование
kill -USR1
: Вместо перезапуска сервера с помощьюapachectl restart
, попробуйте отправить сигналUSR1
процессу Apache. Этот сигнал заставляет сервер пересоздавать дескрипторы файлов логов, что может устранить проблему. Для этого используйте команду:kill -USR1 `cat <HTTPServer path>/logs/httpd.pid`
Это может потребовать немного больше времени для тестирования, но часто оказывается более надежным решением.
-
Параметр
sharedscripts
: Попробуйте использовать параметрsharedscripts
в конфигурацииlogrotate
. Это изменит поведениеpostrotate
, разрешая выполнять команду перезапуска только один раз для всех журналов, а не для каждого отдельно. Это может помочь избежать возможных конфликтов./<HTTPServer path>/logs/access.log { compress dateext maxage 60 rotate 99 daily notifempty missingok sharedscripts postrotate /bin/systemctl reload httpd endscript }
-
Проверка прав доступа: Убедитесь, что у процесса Apache есть необходимые права на запись в новый лог-файл. Отсутствие прав на запись может вызвать откат к старому файлу логов.
-
Мониторинг логов и процессов: Используйте утилиты, такие как
lsof
, чтобы проверить, какие файлы открыты процессом Apache. Это может помочь вам понять, к каким логам он по-прежнему имеет доступ:lsof | grep access.log
Заключение
Проблема с тем, что Apache продолжает записывать в старый файл лога после ротации, может быть связана с особенностями работы с дескрипторами файлов и командой перезапуска. Использование сигнала USR1
, изменение конфигурации logrotate
, а также мониторинг за процессами — это шаги, которые могут помочь решить данную проблему. Следуйте этим рекомендациям, и вы сможете обеспечить корректную ротацию логов без необходимости прибегать к не самым удобным методам, таким как copytruncate
.