Может ли logrotate страдать от состояния гонки?

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

Тем не менее, я обеспокоен условиями гонки. Может ли быть потеря сообщений журнала, если PHP находится в середине записи в журнал, когда logrotate определяет, нужно ли вращать этот журнал, как в последовательности событий ниже? Если нет, то почему?

  1. PHP открывает файл журнала для записи.
  2. PHP пишет строку.
  3. logrotate решает, что файл журнала должен быть повернут.
  4. PHP пишет еще одну строку.
  5. 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.

Итак, в вашем случае:

  1. повернуть файл
  2. удалите general.log.5, если существует
  3. создать general.log с соответствующим атрибутом и собственностью
  4. запускает постротационный скрипт

Ваше приложение будет продолжать писать файл general.log.1, пока не закроет файл или postscript выполняется, и nginx выполняет постепенный перезапуск.

Если ваше приложение всегда закрывает файл журнала через fclose($fp) или использует file_put_contents вы должны опустить nginx Изящный перезапуск.

Другие вопросы по тегам