logrotate: no reload of a Postfix that is not running yet
test / test (push) Waiting to run

The rollout of 0cceb54 to the test server (2026-10-16 04:44 UTC) logged
"postfix/postlog: fatal: the Postfix mail system is not running" and
"error running non-shared postrotate script": the day's rotation was due,
logrotate-loop.sh runs at once when the container starts, and the wrapper
starts Postfix only once the milter sockets are there. Nothing was lost -
no postlogd held the old file, and the one Postfix started a second later
opened the new - but logrotate reported a failure and the loop waited six
hours. The postrotate now runs "postfix reload" only when "postfix status"
says a master runs (Postfix 3.10.13, conf/postfix-script:297-307).

e2e TestStartsOnA27Data also starts on a mail.log whose rotation is due
(a state file of two days before) and wants it rotated with no postrotate
error in the container's log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-16 07:57:09 +03:00
co-authored by Claude Opus 5.5
parent 0cceb549cc
commit 80faf1a901
3 changed files with 27 additions and 1 deletions
+5
View File
@@ -55,6 +55,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
it as quoted-printable for a server that does not announce 8BITMIME, after it as quoted-printable for a server that does not announce 8BITMIME, after
it was signed; `disable_mime_output_conversion=yes` now delivers it as it was signed; `disable_mime_output_conversion=yes` now delivers it as
signed. OpenDKIM's signatures were exposed to this too. signed. OpenDKIM's signatures were exposed to this too.
- **A rotation of `mail.log` due at the container's start logged an error.**
It runs before Postfix does, and its `postfix reload` failed ("the Postfix
mail system is not running"); nothing was lost - the Postfix starting
next opens the new file - but logrotate reported a failure. It reloads
only a running Postfix now.
- **A start on a queue of an earlier image could stop at `postfix check`.** - **A start on a queue of an earlier image could stop at `postfix check`.**
The numbers the image's package accounts get depend on what else it The numbers the image's package accounts get depend on what else it
installs, and the queue under `/data` kept the old ones; `postsuper`, which installs, and the queue under `/data` kept the old ones; `postsuper`, which
+8
View File
@@ -15,7 +15,15 @@
compress compress
delaycompress delaycompress
create 0640 postfix selfpost create 0640 postfix selfpost
# A rotation due when the container starts runs before Postfix does
# (logrotate-loop.sh runs at once, the wrapper waits for the milter
# sockets): no postlogd holds the old file then, the one Postfix starts
# opens the new, and a reload would only fail - "fatal: the Postfix mail
# system is not running", seen at the test server's rollout of
# 2026-10-16. "postfix status" exits 1 while no master runs (Postfix
# 3.10.13, conf/postfix-script:297-307), reload then nothing.
postrotate postrotate
/usr/sbin/postfix status >/dev/null 2>&1 || exit 0
/usr/sbin/postfix reload /usr/sbin/postfix reload
endscript endscript
} }
+14 -1
View File
@@ -64,7 +64,10 @@ for d in active bounce corrupt defer deferred flush hold incoming private saved
done done
mkdir -p $q/maildrop $q/public $q/pid mkdir -p $q/maildrop $q/public $q/pid
chown 4242:4244 $q/maildrop $q/public; chmod 730 $q/maildrop; chmod 710 $q/public chown 4242:4244 $q/maildrop $q/public; chmod 730 $q/maildrop; chmod 710 $q/public
chown root:root $q $q/pid; chmod 755 $q $q/pid` chown root:root $q $q/pid; chmod 755 $q $q/pid
mkdir -p /data/log
echo "Oct 14 00:00:00 mail postfix/master[1]: daemon started" > /data/log/mail.log
printf 'logrotate state -- version 2\n"/data/log/mail.log" 2026-10-14-0:0:0\n' > /data/log/.logrotate.status`
if out, err := exec.Command("docker", "run", "--rm", "--entrypoint", "sh", if out, err := exec.Command("docker", "run", "--rm", "--entrypoint", "sh",
"-v", dataDir+":/data", "selfpost:e2e", "-c", layout).CombinedOutput(); err != nil { "-v", dataDir+":/data", "selfpost:e2e", "-c", layout).CombinedOutput(); err != nil {
t.Fatalf("lay out the 2.7 /data: %v\n%s", err, out) t.Fatalf("lay out the 2.7 /data: %v\n%s", err, out)
@@ -118,4 +121,14 @@ chown root:root $q $q/pid; chmod 755 $q $q/pid`
if !strings.Contains(logs(), "the DKIM keys were copied from /data/opendkim to /data/dkim") { if !strings.Contains(logs(), "the DKIM keys were copied from /data/opendkim to /data/dkim") {
t.Errorf("the entrypoint did not say it copied the keys:\n%s", logs()) t.Errorf("the entrypoint did not say it copied the keys:\n%s", logs())
} }
// A rotation due at the start runs before Postfix does: it rotates, and
// its postrotate asks no reload of a Postfix not running yet (the test
// server's rollout of 2026-10-16 logged "fatal: the Postfix mail system
// is not running"; build/logrotate-mail.conf).
if got := exec1(`test -f /data/log/mail.log.1 && echo rotated`); got != "rotated" {
t.Errorf("the rotation due at the start did not run: %q", got)
}
if l := logs(); strings.Contains(l, "error running non-shared postrotate script") || strings.Contains(l, "logrotate failed") {
t.Errorf("the rotation at the start failed:\n%s", l)
}
} }