Logrotate/Logwatch timing causing less useful reports

This is old-school, but I’ve been using Logwatch to keep an eye on things for a long time. I’ve been updating some boxes to AlmaLinux 10 and finding that my Logwatch e-mails don’t contain as much content as they used to (including very little in the httpd section, for example).

It appears that back in AlmaLinux 8, both Logwatch and Logrotate ran out of /etc/cron.daily:

[kwadmin@mail ~]$ ls -la /etc/cron.daily/
total 24
drwxr-xr-x.   2 root root  4096 Apr  2  2023 .
drwxr-xr-x. 100 root root 12288 Sep 12 02:38 ..
-rwxr-xr-x.   1 root root   434 Oct 15  2023 0logwatch
-rwxr-xr-x.   1 root root   189 Jan  4  2018 logrotate

so logwatch would run first.

Now, in AlmaLinux 10, logrotate runs as a systemd timer, and logwatch still runs out of cron. In my case, 3 hours after logrotate has run. Logwatch doesn’t look at the rotated files:

Preprocessing LogFile: http
 cat '/var/log/nginx/access.log'  | /usr/bin/perl /usr/share/logwatch/scripts/shared/expandrepeats ''| /usr/bin/perl /usr/share/logwatch/scripts/shared/applyhttpdate ''>/var/cache/logwatch/logwatch.99FW20IJ/http

so…logwatch ends up not having much to report on.

This may mostly affect the http reporting section, because it in logrotate it rotates daily.

But basically I think there’s an interaction here that is making it so that logwatch doesn’t see most of what happened in /var/log/nginx/access.log.

I realize this is probably an upstream thing, but I’m not sure where to start here. Things I can think of:

  • Both could be timers, with logrotate depending on logwatch so logwatch runs first. The “problem” with this is that it would only work until logrotate runs, so no reruns, but I don’t normally need to rerun logwatch.
  • Logwatch could actually look at rotated log files.

Both of those seem to be upstream things too.

Hello

Solution : Change the logrotate execution time
logwatch runs daily in the early morning (usually around 4 AM) via cron. Therefore, change the logrotate timer to a later time, such as 6 AM, so logwatch runs first.

  1. Edit logrotate.timer
    Open the timer configuration file with the following command:

sudo systemctl edit logrotate.timer --full

  1. Change the OnCalendar time
    Modify the OnCalendar= line in the file as follows to set it to run daily at 6:00 AM.

[Timer]
OnCalendar=daily 06:00:00
AccuracySec=1h
Persistent=true
Save the file and exit the editor.

Great, thank you!

I’m not all that familiar with timers and the syntax doesn’t make it obvious that you can simply add a time to OnCalendar when looking at the file.

I just installed both of these packages with defaults on a clean new AlmaLinux 10 box. I realize that this is all old-school stuff, but the combination of current defaults seems to have caused this change in behavior.

@kevbo
Hello, the following might be the best solution.
However, I haven’t tested it in my environment.
If you have any questions, please feel free to ask.

thanks

AlmaLinux 10: Run logwatch before logrotate (systemd timer method)

1. Disable logwatch in cron.daily
chmod -x /etc/cron.daily/0logwatch

2. Create a custom systemd service and timer

(a) Create the service file:
/etc/systemd/system/logwatch-before-logrotate.service
-------------------------------
[Unit]
Description=Run logwatch before logrotate

[Service]
Type=oneshot
ExecStart=/usr/sbin/logwatch
-------------------------------

(b) Create the timer file:
/etc/systemd/system/logwatch-before-logrotate.timer
-------------------------------
[Unit]
Description=Run logwatch before logrotate (daily)

[Timer]
OnCalendar=*-*-* 23:45:00
Persistent=true

[Install]
WantedBy=timers.target
-------------------------------

* Set the OnCalendar time to BEFORE the time for logrotate.timer (usually 00:00).

3. Reload systemd and enable the timer
systemctl daemon-reload
systemctl enable --now logwatch-before-logrotate.timer

4. Check the schedule
systemctl list-timers | grep logwatch
systemctl list-timers | grep logrotate

- If logwatch-before-logrotate.timer is listed before logrotate.timer, setup is complete.

That's it! Now logwatch will always run before logrotate and your reports will contain all logs as expected.

I’m working through this same thing. Tryng @redadmin solution. When I check the timers, logwatch is not before logrotate.

systemctl list-timers
NEXT                           LEFT LAST                           PASSED UNIT                            ACTIVATES
<snip>
-                                 - Thu 2026-03-19 00:20:49 CDT   15h ago logrotate.timer                 logrotate.service
-                                 - -                                   - logwatch-before-logrotate.timer logwatch-before-logrotate.service

I tried adjusting logrotate timer to:

Timer]
#OnCalendar=daily
OnCalendar=daily 03:00:00
#RandomizedDelaySec=1h

And logwatch-before-logrotate.timer to:

[Timer]
OnCalendar=daily 02:45:00
Persistent=true

What do I need to fix? I’m a little fuzzy on what happens if the first time is set to have a random delay second. And whether there is any dependency setup so one has to finish before next starts.

I think I sorted it. systemctl was not happy with the format:

OnCalendar=daily 03:00:00

(although

systemd-analyze calendar daily 03:00:00

gave identical result as other format)

I changed it to the

OnCalendar=*-*-* 03:00:00

format and with some stop/start/reloading it worked, now with the timers in the right order, ordered by their NEXT time.

I gather there’s a way to make these have some dependency via their .service file(s), but I don’t know how to do it. I would like to have these as snug as possible from analyze to rotate.

Hi shorton,

Yes, that matches what I saw.

OnCalendar=*-*-* 03:00:00 is the safer form here. RandomizedDelaySec adds an extra delay after the scheduled time, so if you want logwatch to run as close as possible before logrotate, it is better to disable it in this setup.

Also, timer order is not a strict dependency. It only means systemd plans to start them in that order. If you need a stricter sequence, that should be handled at the service level rather than relying only on timer timing.

For a simple and predictable setup, I would use fixed times such as:
logwatch-before-logrotate.timer at 02:45
logrotate.timer at 03:00

That is usually enough to keep logwatch useful before the logs are rotated.

Thanks for sharing your follow-up.

1 Like

Thank you for the clarification. As I dig into wanting the sequential execution, do you see anything wrong with this approach:

Setup one timer for logrotate, which will trigger the preceding targets. This would only work if they all run on the same schedule as I understand it, but would happen sequentially.

logrotate.timer #(task-3, last task)

[Unit]
Description=Daily rotation of log files
Documentation=man:logrotate(8) man:logrotate.conf(5)

[Timer]
OnCalendar=*-*-* 03:45:00
AccuracySec=1m
Persistent=true

[Install]
WantedBy=timers.target

(add lines to existing) logrotate.service

[Unit]
Wants=task-2.service #this service kicks off and waits for task2
After=task-2.service

[Service]
TimeoutStartSec=300


task-2.service

[Unit]
Description=Sequential #2
Wants=task-1.service #task 2 kicks off and waits for task1
After=task-1.service

[Service]
Type=oneshot
# postfix log analysis
ExecStart=/usr/sbin/pflogsumm
TimeoutStartSec=300

StandardOutput=journal
StandardError=journal

task-1.service

[Unit]
Description=Sequential #1

[Service]
Type=oneshot
#logwatch log analysis
ExecStart=/usr/sbin/logwatch
TimeoutStartSec=300

StandardOutput=journal
StandardError=journal

(.service naming for some clarity..)

Hello, thank you for testing this.

From your list-timers output, logwatch-before-logrotate.timer is not scheduled yet because both NEXT and LAST are -. So the issue is not the order yet, but that the custom timer is not active or not loaded correctly.

Also, RandomizedDelaySec= only adds delay. It does not make one timer wait for another.

Could you please check these?

systemctl daemon-reload
systemctl enable --now logwatch-before-logrotate.timer
systemctl status logwatch-before-logrotate.timer
systemctl cat logwatch-before-logrotate.timer

If you share that output, I can help check it.