8c95192a7a
Replaces copytruncate with rename + `postfix reload` (the same mechanism `postfix logrotate` itself uses), closing the up-to-one-second window where copytruncate could drop in-flight delivery lines and leave a send-log row stuck at "queued" forever. logrotate-mail.conf keeps `create 0644 root root` rather than `nocreate` as originally planned: verified on a live container that Postfix recreates the file itself only lazily, on the next write after reload, and at mode 0600 — unreadable by the unprivileged panel process. `create` hands the file back at 0644 immediately after rename, before Postfix ever touches it. logtail.follow() re-drains the old file descriptor once more right before switching to the rotated file, closing the residual gap between the last poll's drain and the rotation check. readLogTail() treats a momentarily missing mail.log as an empty screen rather than a logged error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
27 lines
1.1 KiB
Bash
27 lines
1.1 KiB
Bash
#!/bin/sh
|
|
# Periodic logrotate for /var/log/mail.log (spec 9, 10). Rotation renames the
|
|
# file, recreates it (`create 0644 root root`, matching a cold container
|
|
# start), then runs `postfix reload` (the same mechanism `postfix logrotate`
|
|
# uses): postlogd keeps writing to the renamed inode until reload, and the
|
|
# panel's log-tailer holds its own descriptor on that inode, so nothing
|
|
# written before the reload is lost. `create` (rather than `nocreate`) matters
|
|
# here beyond timing: a reload-triggered recreate lands the file at 0600,
|
|
# which the unprivileged panel process cannot read — confirmed on a live
|
|
# container — so logrotate must be the one to create it at 0644.
|
|
#
|
|
# logrotate itself only rotates once the configured "daily" period has elapsed
|
|
# (tracked in /var/lib/logrotate/status), so it is safe to invoke this more
|
|
# often than daily — polling merely bounds how late a legitimate rotation runs.
|
|
set -eu
|
|
|
|
INTERVAL="${LOGROTATE_INTERVAL_SECONDS:-21600}"
|
|
|
|
while true; do
|
|
if logrotate /etc/logrotate.d/mail; then
|
|
:
|
|
else
|
|
echo "logrotate-loop: logrotate failed, will retry after ${INTERVAL}s" >&2
|
|
fi
|
|
sleep "${INTERVAL}"
|
|
done
|