14

I have a service managed by systemd that has the following systemd config telling systemd to write the logs to a file directly (no syslog or anything)

StandardOutput=file:/var/log/foo/my.log

I have a logrotate rule

/var/log/foo/*.log
{
        rotate 31
        daily
        missingok
        notifempty
        compress
        delaycompress
        sharedscripts
}

What's happening is that the logs are being rotated but the service is still writing to the old rotated file and the new log file stays empty.

I have a similar working setup where the service instead writes to syslog. That one works fine because the logrotate config has

postrotate
                invoke-rc.d rsyslog rotate > /dev/null

, which notifies syslog that its log has been rotated.

The issue is that in my problematic case the log is going directly to the file so I don't know if (or which one) i need to send a similar signal to systemd or to the actual service process.

I found the copytruncate option in logrotate which i'm pretty sure will fix my problem but i'm getting the feeling that this is not the ideal way to do it, otherwise copytruncate would be the default behaviour of logrotate.

How do I solve this problem? do i need to send some signal to systemd? do i need to send some signal to the service process? do i have to use copytruncate in logrotate instead?
If it matters, the service is a java process using logback to write to stdout

2 Answers 2

10

copytruncate is the right answer in this case. It's not the default because it's less common to need it, because you'd have a proper daemon that you can signal to re-open the log file.

The alternative is to restart the service in the post-rotation script, but that may not be convenient or desirable.

0
-2

Logs which are opened via systemd's StandardOutput=file: are opened by the service. You can confirm this with lsof /var/log/mylog.log

So rotating it depends on the service. If the service supports reopening its log files after receiving a certain signal, then you just need to send that signal to the service, not to systemd

For example apache will reopen its log files after receiving either USR1 or HUP. So you would need to send either of those signals to it.

If the service's unit file has an ExecReload line that sends the appropriate signal to the service, you could do it then with:

systemctl reload $service

Otherwise, you have to use another method like

kill -$signal $pid
1
  • 2
    Absolutely incorrect because the "service" in this case has zero logic handling the logging, let alone the fd used to write to the file. If I were to use file:/append: with StandardOutput/StandardError what is the proposed magical way to "reopen" a log file to which my program has no reference whatsoever? Your example of apache is a great demonstration of how smart logging should work, however apache is natively handling its own logging. It is not flowing through systemd at all. Which makes me wonder if you understood the question at all. Systemd is managing the log output.
    – Nicholi
    Jun 16, 2022 at 10:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .