有一个 Web 应用程序 (php/apache2),它在请求处理开始时打开一个日志文件,并在处理完成后关闭它(据我所知)。在日志文件打开和关闭之间,当然会写入条目。
让我们假设在请求处理的中间某处(即一些日志条目已经写入而一些尚未写入)执行日志轮换logrotate
,其配置如下:
/var/log/some/path/*.log {
weekly
missingok
rotate 30
compress
delaycompress
notifempty
create <mode> <owner> <group>
size 10M
}
如果我理解 logrotate 手册页,该create
指令将导致当前日志文件(由正在进行的请求处理打开的文件)被重命名/移动,并创建一个新的空日志文件。如果是这样,那么会发生什么尚未写正在进行的请求处理生成的日志条目?它们会被附加到重命名/移动的文件中吗?或者它们会丢失吗?第二个问题是关于 andpostrotate
或prerotate
指令。在我的例子中我需要它们吗?我能想到的唯一可以放入其中的东西是 apache graceful restart 命令,但我真的需要它吗?
答案1
答案是,apache 不会在每次向文件添加内容时打开和关闭文件,因为这会造成巨大的文件系统开销。它在启动时打开日志文件上的文件句柄,并无限期地保持打开状态。
请注意,该create
指令不是创建新文件的东西,它只是定义在旋转发生时赋予新文件的所有者和模式。
当 apache 写入日志文件时,它会写入打开的文件处理。即使该文件的名称在此期间可能已更改,此句柄仍应附加到现有文件。这就是原始 apache logrotate 配置包含如下块的原因:
postrotate
if [ -f "`. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}`" ]; then
/etc/init.d/apache2 reload > /dev/null
fi
endscript
这是来自 Debian 的。其他人可能会做不同的事情,但效果是导致 apache 重新加载其配置,从而使其重新打开命名日志文件上的文件句柄。由于 logrotate 刚刚创建了一个具有该名称的新空日志文件,因此 apache 将开始写入该文件。
因此,不会丢失任何日志条目,但这种轮换形式确实需要通过postrotate
指令定期重新加载。拥有流量非常大的服务器的人往往不喜欢这种限制,可能会喜欢其他日志记录方法,例如mod_log_spread