logrotate 会遭遇竞争条件吗?

logrotate 会遭遇竞争条件吗?

我有一个 PHP 应用程序,它可以生成大量日志信息。我想使用它logrotate来确保这些日志不会随着时间的推移而失控。

但是,我担心竞争条件。如果 PHP 正在写入日志,然后logrotate确定需要轮换该日志(如下面的事件序列所示),是否会丢失日志消息?如果不是,为什么?

  1. PHP 打开日志文件进行写入。
  2. PHP 写入一行。
  3. logrotate决定日志文件是否应该轮换。
  4. PHP 写入另一行。
  5. PHP 关闭文件资源。

file_put_contents例如,使用 PHP 的会有什么不同吗?更一般地说,通过管道传输到日志文件的输出又会怎样呢?

环境细节:

我在另一台机器上的 nginx 服务器后面使用php5-fpm( )。Version: 5.5.9+dfsg-1ubuntu4.6

我建议的 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脚本只会运行一次,而不是对于每个轮换的日志运行一次。

根据日志旋转手动的:

          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. 运行 postrotate 脚本

您的应用程序将继续写入 general.log.1,直到关闭文件或postscript执行并且 nginx 执行优雅重启。

fclose($fp)如果您的应用程序总是通过或使用关闭日志文件,file_put_contents您应该省略nginx平滑重启。

相关内容