From: Michael Tokarev Subject: re-run postfix start through systemd Date: Fri, 13 Dec 2024 21:13:34 +0300 When `postfix start' (or `postmulti start') command is run from command line, postfix instance is started outside a session manager such as systemd. This is fine for traditional init-based systems, but systemd has a notion of a service which it tracks. Postfix instance started this way line becomes "orphaned", run within user session which started it, confuses session manager and other tools which expects mail service to be running. Systemd exports $INVOCATION_ID when it starts a service. This variable can be used as a (weak) indicator that we're running under systemd, so if it is set, just run `master' process the usual way. But if it is not set, and the system is running under systemd (/run/systemd/system is present), instead of running postfix master process directly, we run the systemd service which corresponds to this instance. Which, in turn, should re-run the same `postfix' command and control will come back to this same place, where we now start `master' the usual way. Only the regular `start' command is handled. All other commands, including `start-fg', are not modified. The service being started is either the main/default postfix instance, if config_directory is /etc/postfix. Or, the service is assumed to be a path unit after /etc/postfix-, like config directory being /etc/postfix-foo for postfix@foo.service, or postfix@foo%2dbar-baz for config directory being /etc/postfix-foo-bar/baz (see man:systemd-escape for details on the naming). Other config directories (not prefixed with /etc/postfix-) are not rescheduled through systemd. Currently $MAIL_VERBOSE and $MAIL_DEBUG are not passed through to the master process started through systemd. It can be implemented if needed. diff --git a/src/postfix/postfix.c b/src/postfix/postfix.c --- a/src/postfix/postfix.c +++ b/src/postfix/postfix.c @@ -218,2 +218,4 @@ /* environment overrides. +/* On a Debian system, this command additionally imports \fBINVOCATION_ID\fR +/* variable (used to detect \fBsystemd\fR(1) presence). /* .IP "\fBsyslog_facility (mail)\fR" @@ -577,2 +579,3 @@ int main(int argc, char **argv) import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + argv_add(import_env, "INVOCATION_ID", NULL); /* systemd, debian-specific */ clean_env(import_env->argv); diff --git a/src/postmulti/postmulti.c b/src/postmulti/postmulti.c --- a/src/postmulti/postmulti.c +++ b/src/postmulti/postmulti.c @@ -331,2 +331,4 @@ /* environment overrides. +/* On a Debian system, this command additionally imports \fBINVOCATION_ID\fR +/* variable (used to detect \fBsystemd\fR(1) presence). /* .IP "\fBmulti_instance_directories (empty)\fR" @@ -1220,2 +1222,3 @@ static void export_helper_environment(INSTANCE *target, int export_flags) import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + argv_add(import_env, "INVOCATION_ID", NULL); /* systemd, debian-specific */ clean_env(import_env->argv); diff --git a/conf/postfix-script b/conf/postfix-script --- a/conf/postfix-script +++ b/conf/postfix-script @@ -133,4 +133,17 @@ start|start-fg) exit 1 } + + if [ -f $queue_directory/debian-systemd-start ] # debian-specific + then # same as in debian-systemd-start patch, keep it here so old systemd unit works + rm -f $queue_directory/debian-systemd-start #XXX read MAIL_DEBUG & MAIL_VERBOSE + rm -f $queue_directory/quick-start + [ -d /run/systemd/system ] && [ -n "$INVOCATION_ID" ] || { + $FATAL "the Postfix mail system is started through systemd but not under systemd?" + exit 1 + } + $daemon_directory/master -w + exit + fi + if [ -f $queue_directory/quick-start ] then @@ -144,4 +160,25 @@ start|start-fg) $daemon_directory/postfix-script check-warn fi + + if [ -d /run/systemd/system ] && [ ! "$INVOCATION_ID" ] && # debian-specific + [ $1 = start ] + then + srv=$(systemd-escape -p $config_directory) || exit 1 + case "$srv" in + (etc-postfix) srv=postfix.service ;; + (etc-postfix\\x2d*) srv=postfix@${srv#*\\x2d}.service ;; + (*) srv= ;; + esac + if [ -n "$srv" ]; then + $INFO "redirecting the Postfix mail system startup to systemd $srv" || exit 1 + touch $queue_directory/debian-systemd-start #XXX write MAIL_DEBUG & MAIL_VERBOSE + systemctl start $srv || { + $FATAL "mail system startup through systemd failed" + exit 1 + } + exit 0 + fi + fi + $INFO starting the Postfix mail system || exit 1 case $1 in