diff --git a/debian/koha-systemd.postinst b/debian/koha-systemd.postinst index 74f0eb8c22..5f0882e383 100644 --- a/debian/koha-systemd.postinst +++ b/debian/koha-systemd.postinst @@ -1,66 +1,128 @@ #!/bin/sh set -e -case "$1" in - configure) - # Reload systemd daemon - systemctl daemon-reload || true +DEFAULTS=/etc/default/koha-common - # On first install (no previous version), enable units for all existing instances - # This handles migration from SysV init to systemd - if [ -z "$2" ]; then - # Stop and disable the legacy SysV koha-common.service if present. - # This service is auto-generated by systemd-sysv-generator from - # /etc/init.d/koha-common and would run in parallel with the native - # systemd units, causing double-starts. Only do this on first - # install: after migration, koha-common.service is our own compat - # unit, and stopping it here would stop every instance on each - # upgrade of this package. - if systemctl is-active --quiet koha-common.service 2>/dev/null; then - systemctl stop koha-common.service || true - fi - if systemctl is-enabled --quiet koha-common.service 2>/dev/null; then - systemctl disable koha-common.service || true +# On a systemd host the daemons started by /etc/init.d/koha-common live in +# the cgroup of the koha-common.service that systemd-sysv-generator created +# for the init script. By the time this postinst runs, the init script has +# already been removed by koha-common's rm_conffile and the koha-* helpers +# already dispatch to systemd, so neither of them can stop those daemons +# any more. Kill the legacy cgroup, then sweep whatever still holds a pid +# file in the instances' run directories (daemon(1) supervisors, starman, +# the Z39.50 responder). +stop_legacy_daemons() { + if systemctl is-active --quiet koha-common.service 2>/dev/null; then + # The generated unit has KillMode=process; a plain stop would leave + # the daemon(1) supervisors and their children running. + systemctl kill --signal=SIGTERM koha-common.service 2>/dev/null || true + systemctl stop koha-common.service 2>/dev/null || true + fi + + for pidfile in /run/koha/*/*.pid; do + [ -f "$pidfile" ] || continue + pid=$(cat "$pidfile" 2>/dev/null) || continue + case "$pid" in + '' | *[!0-9]*) continue ;; + esac + kill -TERM "$pid" 2>/dev/null || true + done + + # Wait (briefly) for them to release their sockets and pid files. + i=0 + while [ "$i" -lt 10 ]; do + alive=0 + for pidfile in /run/koha/*/*.pid; do + [ -f "$pidfile" ] || continue + pid=$(cat "$pidfile" 2>/dev/null) || continue + case "$pid" in + '' | *[!0-9]*) continue ;; + esac + if kill -0 "$pid" 2>/dev/null; then + alive=1 fi + done + [ "$alive" -eq 0 ] && break + sleep 1 + i=$((i + 1)) + done +} - for instance in $(koha-list --enabled 2>/dev/null); do - # Core services: always enable - systemctl enable koha-zebra@${instance}.service 2>/dev/null || true - systemctl enable koha-plack@${instance}.service 2>/dev/null || true - systemctl enable koha-worker@${instance}.service 2>/dev/null || true - systemctl enable koha-worker-long_tasks@${instance}.service 2>/dev/null || true - systemctl enable koha-create-dirs@${instance}.service 2>/dev/null || true - systemctl enable koha@${instance}.target 2>/dev/null || true +# First install (migration from the SysV-managed layout): enable the units +# that correspond to what the init script used to start for each enabled +# instance, then start everything. +enable_existing_instances() { + USE_INDEXER_DAEMON="yes" + if [ -f "$DEFAULTS" ]; then + . "$DEFAULTS" + fi - # Conditional services - # SIP: read the SysV-era flag file DIRECTLY here, not via - # koha-list --sip / is_sip_enabled. The latter now consults - # systemctl is-enabled on systemd hosts (see follow-up 1/3), - # which would return "disabled" for every instance during this - # very first install -- the migration we are about to perform. - # The flag file is the only reliable signal for "did this - # instance have SIP enabled in the SysV-era state we are - # migrating from?". - if [ -e "/var/lib/koha/${instance}/sip.enabled" ]; then - systemctl enable koha-sip@${instance}.service 2>/dev/null || true - fi - if koha-list --enabled --z3950 2>/dev/null | grep -qx "$instance"; then - systemctl enable koha-z3950@${instance}.service 2>/dev/null || true - fi - if koha-list --enabled --elasticsearch 2>/dev/null | grep -qx "$instance"; then - systemctl enable koha-es-indexer@${instance}.service 2>/dev/null || true - else - systemctl enable koha-indexer@${instance}.service 2>/dev/null || true - fi - done - systemctl enable koha.target 2>/dev/null || true + plack_instances=$(koha-list --enabled --plack 2>/dev/null || true) + z3950_instances=$(koha-list --enabled --z3950 2>/dev/null || true) + es_instances=$(koha-list --enabled --elasticsearch 2>/dev/null || true) + + for instance in $(koha-list --enabled 2>/dev/null); do + # Always on + systemctl enable "koha-create-dirs@${instance}.service" 2>/dev/null || true + systemctl enable "koha-zebra@${instance}.service" 2>/dev/null || true + systemctl enable "koha-worker@${instance}.service" 2>/dev/null || true + systemctl enable "koha-worker-long_tasks@${instance}.service" 2>/dev/null || true + systemctl enable "koha@${instance}.target" 2>/dev/null || true + + # Plack: the init script started it for "koha-list --enabled --plack" + # (Apache configuration), so do the same rather than for everyone. + if echo "$plack_instances" | grep -qx "$instance"; then + systemctl enable "koha-plack@${instance}.service" 2>/dev/null || true fi - # On upgrade, restart running Koha services so they pick up new code/unit files - if [ -n "$2" ]; then - deb-systemd-invoke try-restart \ - 'koha-*@*.service' \ - >/dev/null || true + # SIP: read the SysV-era flag file DIRECTLY here, not via + # koha-list --sip / is_sip_enabled. The latter consults + # systemctl is-enabled on systemd hosts, which is "disabled" for + # every instance during this very first install. The flag file is + # the only signal for "did this instance have SIP enabled in the + # SysV-era state we are migrating from?". + if [ -e "/var/lib/koha/${instance}/sip.enabled" ]; then + systemctl enable "koha-sip@${instance}.service" 2>/dev/null || true + fi + + if echo "$z3950_instances" | grep -qx "$instance"; then + systemctl enable "koha-z3950@${instance}.service" 2>/dev/null || true + fi + + # Indexing: the ES indexer for Elasticsearch instances, otherwise + # the Zebra indexer daemon if /etc/default/koha-common asks for it, + # which is what the init script did. + if echo "$es_instances" | grep -qx "$instance"; then + systemctl enable "koha-es-indexer@${instance}.service" 2>/dev/null || true + elif [ "$USE_INDEXER_DAEMON" = "yes" ]; then + systemctl enable "koha-indexer@${instance}.service" 2>/dev/null || true + fi + done + + systemctl enable koha.target 2>/dev/null || true + systemctl enable koha-common.service 2>/dev/null || true +} + +case "$1" in + configure) + if [ -z "$2" ]; then + stop_legacy_daemons + fi + + systemctl daemon-reload || true + + if [ -z "$2" ]; then + enable_existing_instances + deb-systemd-invoke start koha.target koha-common.service >/dev/null || true + else + # Upgrade: restart the running per-component units so they pick + # up new code and unit files. deb-systemd-invoke takes unit + # names, not patterns, so enumerate them first. + units=$(systemctl list-units --plain --no-legend --state=active 'koha-*@*.service' 2>/dev/null | awk '{print $1}') + if [ -n "$units" ]; then + # shellcheck disable=SC2086 + deb-systemd-invoke try-restart $units >/dev/null || true + fi fi ;; esac diff --git a/debian/koha-systemd.postrm b/debian/koha-systemd.postrm new file mode 100644 index 0000000000..f4726e4187 --- /dev/null +++ b/debian/koha-systemd.postrm @@ -0,0 +1,21 @@ +#!/bin/sh +set -e + +case "$1" in + purge) + # Drop the enablement symlinks created by koha-create, koha-* --enable + # and the postinst migration. + rm -rf /etc/systemd/system/koha.target.wants + rm -rf /etc/systemd/system/koha@*.target.wants + rm -f /etc/systemd/system/multi-user.target.wants/koha.target + rm -f /etc/systemd/system/multi-user.target.wants/koha-common.service + ;; +esac + +if [ -d /run/systemd/system ]; then + systemctl daemon-reload >/dev/null 2>&1 || true +fi + +#DEBHELPER# + +exit 0 diff --git a/debian/koha-systemd.prerm b/debian/koha-systemd.prerm index 651fc77873..78b87c307d 100644 --- a/debian/koha-systemd.prerm +++ b/debian/koha-systemd.prerm @@ -3,8 +3,11 @@ set -e case "$1" in remove|deconfigure) + # Stop everything while the unit files are still present. Otherwise + # the daemons keep running with no unit left to manage them, and a + # swap to koha-sysv would start a second copy of each. if [ -d /run/systemd/system ]; then - systemctl --system daemon-reload >/dev/null || true + deb-systemd-invoke stop koha-common.service koha.target >/dev/null || true fi ;; esac