Может ли logrotate страдать от состояния гонки?
У меня есть приложение PHP, которое может генерировать довольно много информации журнала. Я хотел бы использовать logrotate
чтобы убедиться, что эти журналы не выходят из-под контроля со временем.
Тем не менее, я обеспокоен условиями гонки. Может ли быть потеря сообщений журнала, если PHP находится в середине записи в журнал, когда logrotate
определяет, нужно ли вращать этот журнал, как в последовательности событий ниже? Если нет, то почему?
- PHP открывает файл журнала для записи.
- PHP пишет строку.
logrotate
решает, что файл журнала должен быть повернут.- PHP пишет еще одну строку.
- PHP закрывает файловый ресурс.
Будет ли использовать PHP file_put_contents
Например, какая разница? А как насчет вывода в целом, который передается в файл журнала?
Особенности окружающей среды:
я использую php5-fpm
(Version: 5.5.9+dfsg-1ubuntu4.6
) за сервером nginx на другом компьютере.
Моя предложенная конфигурация logrotate (я еще ничего не настроил) будет примерно такой (в /etc/logrotate.d/my-app
):
/var/my-app-data/logs/*.log {
missingok
notifempty
weekly
size 20M
rotate 4
}
Несколько примеров моего PHP-кода:
$res = file_put_contents('/var/my-app-data/logs/general.log', date('[d/m/Y H:i:s]') . ' Something noteworthy has happened!' . "\n", FILE_APPEND);
Возможно, в будущем мы захотим использовать что-то похожее на код ниже:
$fp = fopen('/var/my-app-data/logs/general.log', 'a');
fwrite($fp, date('[d/m/Y H:i:s]') . ' Starting process...' . "\n");
// ...
fwrite($fp, date('[d/m/Y H:i:s]') . ' Something happened!' . "\n");
// ...
fwrite($fp, date('[d/m/Y H:i:s]') . ' Something happened!' . "\n");
// ...
fwrite($fp, date('[d/m/Y H:i:s]') . ' End of process.' . "\n");
fclose($fp);
1 ответ
Когда приложение открывает файл, продолжайте писать в нем, даже если он был перемещен. Поэтому, если вы хотите быть уверенным, что не потеряете информацию, вам следует отправить сигнал приложению, чтобы оно высвободило ресурсы.
Вы можете попробовать эту конфигурацию:
/var/my-app-data/logs/general.log {
missingok
notifempty
size 20M
rotate 4
create mode owner group
sharedscripts
postrotate
nginx command to do graceful restart
endscript
}
это general.log
файл вращается всякий раз, когда он растет 20M
по размеру, после прохождения 4
повороты, файл удаляется.
sharedscripts
означает, что postrotate
Скрипт будет запускаться только один раз, а не один раз для каждого вращающегося журнала.
Согласно руководству пользователя logrotate:
create mode owner group
Immediately after rotation (before the postrotate script is run)
the log file is created (with the same name as the log file just
rotated). mode specifies the mode for the log file in octal
(the same as chmod(2)), owner specifies the user name who will
own the log file, and group specifies the group the log file
will belong to.
Итак, в вашем случае:
- повернуть файл
- удалите general.log.5, если существует
- создать general.log с соответствующим атрибутом и собственностью
- запускает постротационный скрипт
Ваше приложение будет продолжать писать файл general.log.1, пока не закроет файл или postscript
выполняется, и nginx выполняет постепенный перезапуск.
Если ваше приложение всегда закрывает файл журнала через fclose($fp)
или использует file_put_contents
вы должны опустить nginx
Изящный перезапуск.