如何通过“file:”配置正确记录由 systemd 管理的服务日志

如何通过“file:”配置正确记录由 systemd 管理的服务日志

我有一个由 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

相关内容