带有 logrotate 的 rsyslog:重新加载 rsyslog 与 copytruncate

Mat*_*tan 23 logrotate rsyslog

我正在使用默认的 rsyslog 和 logrotate 实用程序在 Ubuntu 14 上工作。

在默认的 rsyslog logrotate/etc/logrotate.d/rsyslog配置中,我看到以下内容:

/var/log/syslog
{
        rotate 7
        daily
        missingok
        notifempty
        delaycompress
        compress
        postrotate
                reload rsyslog >/dev/null 2>&1 || true
        endscript
}
Run Code Online (Sandbox Code Playgroud)

据我了解,建议在所有 logrotate 场景中使用 copytruncate,因为它不会移动当前日志,而是截断日志,因此任何具有打开文件处理程序的进程都能够继续写入它。

那么默认配置如何使用 rsyslog 重新加载功能呢?

sho*_*hok 37

要回答您的问题,您首先需要了解 reload 和 copytruncate 的不同权衡:

  • reload:旧的日志文件被重命名,写入该日志的进程被通知(通过 Unix 信号)重新创建其日志文件。这是最快/低开销的方法:重命名/移动操作非常快,并且具有恒定的执行时间。此外,它几乎是原子操作:这意味着(几乎)在移动/重新加载期间不会丢失任何日志条目。另一方面,您需要一个能够重新加载和重新打开其日志文件的进程。rsyslog就是这样一个过程,所以默认的logrotate config使用reload的方式。rsyslog 上游强烈建议将此模式与 rsyslog 一起使用。
  • copytruncate:将旧日志文件复制到存档文件中,然后将其截断以“删除”旧日志行。虽然截断操作非常快,但副本可能很长(取决于您的日志文件有多大)。此外,在复制操作(记住,它可能很慢)和截断之间的时间内,一些日志条目可能会丢失。由于这些原因,默认情况下不会将 copytruncate 用于能够重新加载和重新创建其日志文件的服务。另一方面,如果服务器无法重新加载/重新创建日志文件,那么 copytruncate 是您最安全的选择。换句话说,它不需要任何服务级别的支持。rsyslog 上游项目强烈建议不要使用这种模式。


Rai*_*rds 27

作为 rsyslog 的作者,copytruncate 实际上是一个非常非常非常糟糕的选择。它本质上是活泼的,使用它几乎可以保证您会丢失日志数据。文件写入的频率越高,您丢失的就越多。这不仅是最后一行的一部分,还可以是数百个,具体取决于旋转发生时系统的确切时间和状态。

当文件移动并创建新的 inode(文件)时,rsyslog 会跟踪前一个文件并完成处理。所以在这种情况下你没有任何损失。保证(除非您卸载文件系统...)。

关于“reopenOnTruncate”:我个人认为reopenOnTruncate 在其他方面也很活跃,尤其是在NFS 等方面。前段时间我完全删除了该功能,但后来被说服将类似的功能合并回来。它很可能会永远保持“实验性”,因为我真的知道人们会在负载非常重的系统上遇到麻烦。“copytruncate”根本就不是处理日志文件的体面模式。

我目前致力于重构 imfile(ETA 8.34 或 8.35)。重构后的版本可能能够防止因 API 竞争而意外重新发送,但也无法防止数据丢失——因为这在概念上是不可能的。