我有一个由 systemd 管理的服务,它具有以下 systemd 配置,告诉 systemd 将日志直接写入文件(没有 syslog 或任何内容)
StandardOutput=file:/var/log/foo/my.log
我有一个 logrotate 规则
/var/log/foo/*.log
{
rotate 31
daily
missingok
notifempty
compress
delaycompress
sharedscripts
}
发生的情况是日志正在轮换,但服务仍在写入旧的轮换文件,而新日志文件仍为空。
我有一个类似的工作设置,其中服务写入系统日志。这个工作正常,因为 logrotate 配置有
postrotate
invoke-rc.d rsyslog rotate > /dev/null
,它通知 syslog 它的日志已被轮换。
问题是,在我有问题的情况下,日志直接发送到文件,因此我不知道是否(或哪一个)需要向 systemd 或实际服务进程发送类似的信号。
我copytruncate
在 logrotate 中找到了这个选项,我很确定它会解决我的问题,但我感觉这不是理想的方法,否则copytruncate
将是 logrotate 的默认行为。
我该如何解决这个问题?我需要向 systemd 发送一些信号吗?我需要向服务进程发送一些信号吗?我必须copytruncate
在 logrotate 中使用吗?
如果重要的话,该服务是一个使用 logback 写入 stdout 的 java 进程
答案1
copytruncate
在这种情况下是正确的答案。它不是默认值,因为很少需要它,因为您有一个适当的守护进程,您可以发出信号以重新打开日志文件。
另一种方法是在轮换后脚本中重新启动服务,但这可能不方便或不理想。
答案2
通过 systemd 打开的日志StandardOutput=file:
由该服务打开。您可以通过以下方式确认这一点lsof /var/log/mylog.log
所以轮换取决于服务。如果服务支持在收到某个信号后重新打开其日志文件,那么您只需将该信号发送到服务,不是到系统
例如,apache 在收到 USR1 或 HUP 后将重新打开其日志文件。因此,您需要向其发送其中一个信号。
如果服务的单元文件有一个 ExecReload 行向服务发送适当的信号,那么您可以使用以下命令来执行此操作:
systemctl reload $service
否则,你必须使用另一种方法,例如
kill -$signal $pid