diff options
author | Luca Boccassi <luca.boccassi@microsoft.com> | 2021-07-26 12:02:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-26 12:02:37 +0200 |
commit | c5a421b3b9d94b3a6736ac61aa5b085e66f2f76a (patch) | |
tree | 28756e7ab5b34c350c83fc33ff8f9ff330e8825a | |
parent | test: make sure we don't access an unbound variable (diff) | |
parent | update-helper: also add "user-reexec" verb (diff) | |
download | systemd-c5a421b3b9d94b3a6736ac61aa5b085e66f2f76a.tar.xz systemd-c5a421b3b9d94b3a6736ac61aa5b085e66f2f76a.zip |
Merge pull request #20276 from keszybz/rpm-restart-wip
Reload user daemons and restart user services at the end of the rpm transaction
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | meson_options.txt | 2 | ||||
-rw-r--r-- | src/rpm/macros.systemd.in | 42 | ||||
-rw-r--r-- | src/rpm/meson.build | 13 | ||||
-rwxr-xr-x | src/rpm/systemd-update-helper.in | 116 | ||||
-rw-r--r-- | src/rpm/triggers.systemd.in | 79 | ||||
-rw-r--r-- | src/rpm/triggers.systemd.sh.in | 36 |
8 files changed, 220 insertions, 74 deletions
@@ -193,7 +193,7 @@ REQUIREMENTS: python-jinja2 python-lxml (optional, required to build the indices) python >= 3.5 - meson >= 0.46 (>= 0.49 is required to build position-independent executables) + meson >= 0.47 (>= 0.49 is required to build position-independent executables) ninja gcc, awk, sed, grep, and similar tools clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs diff --git a/meson.build b/meson.build index 815c223171..171d7bcfab 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,7 @@ project('systemd', 'c', 'localstatedir=/var', 'warning_level=2', ], - meson_version : '>= 0.46', + meson_version : '>= 0.47', ) libsystemd_version = '0.32.0' @@ -255,6 +255,7 @@ conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', join_paths(rootlib conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge')) conf.set_quoted('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata')) conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent')) +conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', join_paths(rootlibexecdir, 'systemd-update-helper')) conf.set_quoted('SYSTEMD_USERWORK_PATH', join_paths(rootlibexecdir, 'systemd-userwork')) conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', join_paths(rootlibexecdir, 'systemd-veritysetup')) conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'system')) @@ -271,6 +272,7 @@ conf.set_quoted('TMPFILES_DIR', tmpfilesdir) conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir) conf.set_quoted('UDEV_HWDB_DIR', udevhwdbdir) conf.set_quoted('UDEV_RULES_DIR', udevrulesdir) +conf.set_quoted('UPDATE_HELPER_USER_TIMEOUT', get_option('update-helper-user-timeout')) conf.set_quoted('USER_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'user')) conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir) conf.set_quoted('USER_ENV_GENERATOR_DIR', userenvgeneratordir) diff --git a/meson_options.txt b/meson_options.txt index b60261ac24..50f2b7b5e9 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -182,6 +182,8 @@ option('xinitrcdir', type : 'string', value : '', description : 'directory for xinitrc files') option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d', description : 'directory for rpm macros ["no" disables]') +option('update-helper-user-timeout', type : 'string', value : '15s', + description : 'how long to wait for user manager operations') option('pamlibdir', type : 'string', description : 'directory for PAM modules') option('pamconfdir', type : 'string', diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in index 3a0169a85f..caa2e45595 100644 --- a/src/rpm/macros.systemd.in +++ b/src/rpm/macros.systemd.in @@ -46,31 +46,33 @@ OrderWithRequires(postun): systemd \ %systemd_post() \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_post}} \ -if [ $1 -eq 1 ] && [ -x %{_bindir}/systemctl ]; then \ +if [ $1 -eq 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ # Initial installation \ - %{_bindir}/systemctl --no-reload preset %{?*} || : \ + {{SYSTEMD_UPDATE_HELPER_PATH}} install-system-units %{?*} || : \ fi \ %{nil} -%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}} +%systemd_user_post() \ +%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_post}} \ +if [ $1 -eq 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ + # Initial installation \ + {{SYSTEMD_UPDATE_HELPER_PATH}} install-user-units %{?*} || : \ +fi \ +%{nil} %systemd_preun() \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_preun}} \ -if [ $1 -eq 0 ] && [ -x %{_bindir}/systemctl ]; then \ +if [ $1 -eq 0 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ # Package removal, not upgrade \ - if [ -d /run/systemd/system ]; then \ - %{_bindir}/systemctl --no-reload disable --now %{?*} || : \ - else \ - %{_bindir}/systemctl --no-reload disable %{?*} || : \ - fi \ + {{SYSTEMD_UPDATE_HELPER_PATH}} remove-system-units %{?*} || : \ fi \ %{nil} %systemd_user_preun() \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_preun}} \ -if [ $1 -eq 0 ] && [ -x %{_bindir}/systemctl ]; then \ +if [ $1 -eq 0 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ # Package removal, not upgrade \ - %{_bindir}/systemctl --global disable %{?*} || : \ + {{SYSTEMD_UPDATE_HELPER_PATH}} remove-user-units %{?*} || : \ fi \ %{nil} @@ -84,16 +86,18 @@ fi \ %systemd_postun_with_restart() \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \ -if [ $1 -ge 1 ] && [ -x %{_bindir}/systemctl ]; then \ +if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ # Package upgrade, not uninstall \ - for unit in %{?*}; do \ - %{_bindir}/systemctl set-property $unit Markers=+needs-restart || : \ - done \ + {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-system-units %{?*} || : \ fi \ %{nil} %systemd_user_postun_with_restart() \ -%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \ +%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_postun_with_restart}} \ +if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ + # Package upgrade, not uninstall \ + {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-user-units %{?*} || : \ +fi \ %{nil} %udev_hwdb_update() %{nil} @@ -105,17 +109,17 @@ fi \ # Deprecated. Use %tmpfiles_create_package instead %tmpfiles_create() \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# tmpfiles_create}} \ -[ -x %{_bindir}/systemd-tmpfiles ] && %{_bindir}/systemd-tmpfiles --create %{?*} || : \ +command -v systemd-tmpfiles >/dev/null && systemd-tmpfiles --create %{?*} || : \ %{nil} # Deprecated. Use %sysusers_create_package instead %sysusers_create() \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# sysusers_create}} \ -[ -x %{_bindir}/systemd-sysusers ] && %{_bindir}/systemd-sysusers %{?*} || : \ +command -v systemd-sysusers >/dev/null && systemd-sysusers %{?*} || : \ %{nil} %sysusers_create_inline() \ -[ -x %{_bindir}/systemd-sysusers ] && %{_bindir}/systemd-sysusers - <<SYSTEMD_INLINE_EOF || : \ +command -v systemd-sysusers >/dev/null && systemd-sysusers - <<SYSTEMD_INLINE_EOF || : \ %{?*} \ SYSTEMD_INLINE_EOF\ %{nil} diff --git a/src/rpm/meson.build b/src/rpm/meson.build index fc72fee73c..2ad3308cc1 100644 --- a/src/rpm/meson.build +++ b/src/rpm/meson.build @@ -1,9 +1,13 @@ # SPDX-License-Identifier: LGPL-2.1-or-later in_files = [ - ['macros.systemd', rpmmacrosdir != 'no'], - ['triggers.systemd', false], - ['triggers.systemd.sh', false]] + ['macros.systemd', rpmmacrosdir != 'no', rpmmacrosdir], + + # we conditionalize on rpmmacrosdir, but install into rootlibexecdir + ['systemd-update-helper', rpmmacrosdir != 'no', rootlibexecdir, 'rwxr-xr-x'], + + ['triggers.systemd', false], + ['triggers.systemd.sh', false]] # The last two don't get installed anywhere, one of them needs to included in # the rpm spec file definition instead. @@ -17,6 +21,7 @@ foreach tuple : in_files command : [meson_render_jinja2, config_h, '@INPUT@'], capture : true, install : tuple[1], - install_dir : rpmmacrosdir, + install_dir : tuple.length() > 2 ? tuple[2] : '', + install_mode : tuple.length() > 3 ? tuple[3] : false, build_by_default : true) endforeach diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in new file mode 100755 index 0000000000..0c6675a9db --- /dev/null +++ b/src/rpm/systemd-update-helper.in @@ -0,0 +1,116 @@ +#!/bin/bash +set -eu +set -o pipefail + +command="${1:?}" +shift + +command -v systemctl >/dev/null || exit 0 + +case "$command" in + install-system-units) + systemctl --no-reload preset "$@" + ;; + + install-user-units) + systemctl --no-reload preset --global "$@" + ;; + + remove-system-units) + if [ -d /run/systemd/system ]; then + systemctl --no-reload disable --now "$@" + else + systemctl --no-reload disable "$@" + fi + ;; + + remove-user-units) + systemctl --global disable "$@" + + [ -d /run/systemd/system ] || exit 0 + + users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') + for user in $users; do + SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \ + systemctl --user -M "$user@" disable --now "$@" & + done + wait + ;; + + mark-restart-system-units) + [ -d /run/systemd/system ] || exit 0 + + for unit in "$@"; do + systemctl set-property "$unit" Markers=+needs-restart & + done + wait + ;; + + mark-restart-user-units) + [ -d /run/systemd/system ] || exit 0 + + users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') + for user in $users; do + SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \ + systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart & + done + wait + ;; + + system-reload-restart|system-reload|system-restart) + if [ -n "$*" ]; then + echo "Unexpected arguments for '$command': $*" + exit 2 + fi + + [ -d /run/systemd/system ] || exit 0 + + if [[ "$command" =~ reload ]]; then + systemctl daemon-reload + fi + + if [[ "$command" =~ restart ]]; then + systemctl reload-or-restart --marked + fi + ;; + + user-reload-restart|user-reload|user-restart|user-reexec) + if [ -n "$*" ]; then + echo "Unexpected arguments for '$command': $*" + exit 2 + fi + + [ -d /run/systemd/system ] || exit 0 + + users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') + + if [[ "$command" =~ reexec ]]; then + for user in $users; do + SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \ + systemctl --user -M "$user@" daemon-reexec & + done + wait + fi + + if [[ "$command" =~ reload ]]; then + for user in $users; do + SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \ + systemctl --user -M "$user@" daemon-reload & + done + wait + fi + + if [[ "$command" =~ restart ]]; then + for user in $users; do + SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \ + systemctl --user -M "$user@" reload-or-restart --marked & + done + wait + fi + ;; + + *) + echo "Unknown verb '$command'" + exit 3 + ;; +esac diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in index b33d2212e8..8aeb2049c1 100644 --- a/src/rpm/triggers.systemd.in +++ b/src/rpm/triggers.systemd.in @@ -13,20 +13,19 @@ -- upgraded. We care about the case where a package is initially -- installed, because other cases are covered by the *un scriptlets, -- so sometimes we will reload needlessly. -if posix.access("/run/systemd/system") then - pid = posix.fork() - if pid == 0 then - assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) - elseif pid > 0 then - posix.wait(pid) - end +pid = posix.fork() +if pid == 0 then + assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload-restart")) +elseif pid > 0 then + posix.wait(pid) +end - pid = posix.fork() - if pid == 0 then - assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked")) - elseif pid > 0 then - posix.wait(pid) - end +%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user +pid = posix.fork() +if pid == 0 then + assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart")) +elseif pid > 0 then + posix.wait(pid) end %transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system @@ -35,24 +34,38 @@ end -- On upgrade, we need to run daemon-reload after any new unit files -- have been installed, but before %postun scripts in packages get -- executed. -if posix.access("/run/systemd/system") then - pid = posix.fork() - if pid == 0 then - assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) - elseif pid > 0 then - posix.wait(pid) - end +pid = posix.fork() +if pid == 0 then + assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system +-- Execute daemon-reload in user managers. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload")) +elseif pid > 0 then + posix.wait(pid) end %transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system --- We restart remaining services that should be restarted here. -if posix.access("/run/systemd/system") then - pid = posix.fork() - if pid == 0 then - assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked")) - elseif pid > 0 then - posix.wait(pid) - end +-- We restart remaining system services that should be restarted here. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user +-- We restart remaining user services that should be restarted here. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart")) +elseif pid > 0 then + posix.wait(pid) end %transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}} @@ -62,7 +75,7 @@ end if posix.access("/run/systemd/system") then pid = posix.fork() if pid == 0 then - assert(posix.exec("%{_bindir}/systemd-sysusers")) + assert(posix.execp("systemd-sysusers")) elseif pid > 0 then posix.wait(pid) end @@ -74,7 +87,7 @@ end if posix.access("/run/systemd/system") then pid = posix.fork() if pid == 0 then - assert(posix.exec("%{_bindir}/systemd-hwdb", "update")) + assert(posix.execp("systemd-hwdb", "update")) elseif pid > 0 then posix.wait(pid) end @@ -86,7 +99,7 @@ end if posix.access("/run/systemd/system") then pid = posix.fork() if pid == 0 then - assert(posix.exec("%{_bindir}/journalctl", "--update-catalog")) + assert(posix.execp("journalctl", "--update-catalog")) elseif pid > 0 then posix.wait(pid) end @@ -111,7 +124,7 @@ end if posix.access("/run/systemd/system") then pid = posix.fork() if pid == 0 then - assert(posix.exec("%{_bindir}/systemd-tmpfiles", "--create")) + assert(posix.execp("systemd-tmpfiles", "--create")) elseif pid > 0 then posix.wait(pid) end @@ -123,7 +136,7 @@ end if posix.access("/run/systemd/system") then pid = posix.fork() if pid == 0 then - assert(posix.exec("%{_bindir}/udevadm", "control", "--reload")) + assert(posix.execp("udevadm", "control", "--reload")) elseif pid > 0 then posix.wait(pid) end diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in index 22abad9812..694cd94e8d 100644 --- a/src/rpm/triggers.systemd.sh.in +++ b/src/rpm/triggers.systemd.sh.in @@ -14,10 +14,10 @@ # upgraded. We care about the case where a package is initially # installed, because other cases are covered by the *un scriptlets, # so sometimes we will reload needlessly. -if test -d "/run/systemd/system"; then - %{_bindir}/systemctl daemon-reload || : - %{_bindir}/systemctl reload-or-restart --marked || : -fi +{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || : + +%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user +{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || : %transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system # On removal, we need to run daemon-reload after any units have been @@ -25,36 +25,40 @@ fi # On upgrade, we need to run daemon-reload after any new unit files # have been installed, but before %postun scripts in packages get # executed. -if test -d "/run/systemd/system"; then - %{_bindir}/systemctl daemon-reload || : -fi +{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || : + +%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user +# Execute daemon-reload in user managers. +{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || : %transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system -# We restart remaining services that should be restarted here. -if test -d "/run/systemd/system"; then - %{_bindir}/systemctl reload-or-restart --marked || : -fi +# We restart remaining system services that should be restarted here. +{{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || : + +%transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user +# We restart remaining user services that should be restarted here. +{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || : %transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}} # This script will process files installed in {{SYSUSERS_DIR}} to create # specified users automatically. The priority is set such that it # will run before the tmpfiles file trigger. if test -d "/run/systemd/system"; then - %{_bindir}/systemd-sysusers || : + systemd-sysusers || : fi %transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}} # This script will automatically invoke hwdb update if files have been # installed or updated in {{UDEV_HWDB_DIR}}. if test -d "/run/systemd/system"; then - %{_bindir}/systemd-hwdb update || : + systemd-hwdb update || : fi %transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}} # This script will automatically invoke journal catalog update if files # have been installed or updated in {{SYSTEMD_CATALOG_DIR}}. if test -d "/run/systemd/system"; then - %{_bindir}/journalctl --update-catalog || : + journalctl --update-catalog || : fi %transfiletriggerin -P 1000700 -- {{BINFMT_DIR}} @@ -71,14 +75,14 @@ fi # tmpfiles automatically. The priority is set such that it will run # after the sysusers file trigger, but before any other triggers. if test -d "/run/systemd/system"; then - %{_bindir}/systemd-tmpfiles --create || : + systemd-tmpfiles --create || : fi %transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}} # This script will automatically update udev with new rules if files # have been installed or updated in {{UDEV_RULES_DIR}}. if test -e /run/udev/control; then - %{_bindir}/udevadm control --reload || : + udevadm control --reload || : fi %transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}} |