我正在使用默认的 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
}
据我所知,建议在所有 logrotate 场景中使用 copytruncate,因为它不会移动当前日志,而是截断日志,以便任何具有打开文件处理程序的进程都能够继续写入它。
那么如何使用 rsyslog 重新加载功能来代替默认配置呢?
答案1
要回答您的问题,您首先需要了解 reload 和 copytruncate 的不同权衡:
- 重新加载:重命名旧日志文件,并通知写入该日志的进程(通过 Unix 信号)重新创建其日志文件。这是最快/开销最低的方法:重命名/移动操作非常快,并且执行时间恒定。此外,它几乎是一个原子操作:这意味着在移动/重新加载期间(几乎)不会丢失任何日志条目。另一方面,你需要一个能够重新加载并重新打开其日志文件的进程。Rsyslog 就是这样一个进程,因此默认的 logrotate 配置使用 reload 方法。rsyslog 上游强烈建议将此模式与 rsyslog 一起使用。
- 复制截断:旧日志文件是复制写入存档文件,然后将其截断以“删除”旧日志行。虽然截断操作非常快,但复制过程可能相当长(取决于日志文件的大小)。此外,在复制操作(请记住,它可能很慢)和截断之间的时间内,一些日志条目可能会丢失。出于这些原因,默认情况下,对于能够重新加载和重新创建日志文件的服务,不会使用 copytruncate。另一方面,如果服务器不是由于能够重新加载/重新创建日志文件,copytruncate 是最安全的选择。换句话说,它不需要任何服务级别支持。rsyslog 上游项目强烈建议不要使用此模式。
答案2
作为 rsyslog 的作者,copytruncate 实际上是一个非常非常糟糕的选择。它本质上很危险,使用它几乎可以保证您会丢失日志数据。文件写入的频率越高,丢失的数据就越多。而且这不仅仅是最后一行的一部分,而是可能有几百行,具体取决于轮换发生时的确切时间和系统状态。
当文件被移动并创建新的 inode(文件)时,rsyslog 会跟踪前一个文件并完成处理。因此在这种情况下您不会有任何损失。保证(除非您卸载文件系统...)。
关于“reopenOnTruncate”:我个人认为,reopenOnTruncate 在其他方面也存在问题,尤其是在 NFS 等情况下。前段时间,我完全删除了该功能,但后来被说服重新合并了类似的功能。它很可能永远处于“实验”阶段,因为我确实知道人们在负载非常重的系统上会遇到麻烦。“copytruncate”根本不是处理日志文件的合适模式。
我目前正在重构 imfile(ETA 8.34 或 8.35)。重构后的版本可能能够防止由于 API 竞争而导致的意外重新发送,但也无法防止数据丢失 - 因为这在概念上是不可能的。
答案3
这完全取决于进程如何写入日志。
copytruncate
仅当日志消息附加到文件时才有效(例如whatever >> logfile
。
而不是在重定向输出时(例如whatever > logfile
)。
答案4
具体来说,对于 rsyslog 来说,保持现状可能更有意义。
基本原因是 rsyslog 具有内部队列,可以在其输出句柄不可用的情况下使用。
重新加载将 a) 导致 rsyslog 重新创建其自己的日志文件,以及 b) 导致任何排队事件在创建时被刷新到文件中。
copytruncate 可能没有什么危害(尽管我担心部分写入的行会被截断),但我倾向于认为从完整性的角度来看复制/删除/重新加载“更安全”。
正如@所提到的骗子,由于 rsyslog 可以处理其文件不可用的情况,因此没有令人信服的理由使用 copytruncate。
正如@所提到的谢利瓦诺夫·帕维尔,rsyslog 实际上需要特定的配置才能正确处理复制截断。
因此,如果仅仅因为使用该reload
方法需要与默认配置的偏差较小,我就会保留它。