From a4e1732e3553b7c039d23f89082fe23b058aac59 Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Sun, 29 Nov 2020 03:39:28 -0500 Subject: Fix restart.sh to look at what's actually booted The old code was wrong because e.g. systemd can be *installed* on the system, but not actually used as PID1. In that case we would pick `systemctl`, but it wouldn't actually work because PID1 was some other init system. --- debian/bin/restart.sh | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'debian/bin') diff --git a/debian/bin/restart.sh b/debian/bin/restart.sh index 34fce0670..acbec3dc7 100755 --- a/debian/bin/restart.sh +++ b/debian/bin/restart.sh @@ -11,16 +11,29 @@ # # This script is used by the Debian/Ubuntu/Fedora/CentOS packages. -get_service_command() { - for command in systemctl service; do - if which $command &>/dev/null; then - echo $command && return +# This is the Right Way(tm) to check if we are booted with +# systemd, according to sd_booted(3) +if [ -d /run/systemd/system ]; then + cmd=systemctl +else + # Everything else is really hard to figure out, so we just use + # service(8) if it's available - that works with most init + # systems/distributions I know of, including FreeBSD + if type service >/dev/null 2>&1; then + cmd=service + else + # If even service(8) isn't available, we just try /etc/init.d + # and hope for the best + if [ -d /etc/init.d ]; then + cmd=sysv + else + echo "Unable to detect a way to restart Jellyfin; bailing out" 1>&2 + echo "Please report this bug to https://github.com/jellyfin/jellyfin/issues" 1>&2 + exit 1 fi - done - echo "sysv" -} + fi +fi -cmd="$( get_service_command )" echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') -- cgit v1.2.3 From ce82932c9a4a33fd142d56e5b0683429329751ee Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Sun, 29 Nov 2020 03:47:18 -0500 Subject: Remove useless which(1) calls in restart.sh at(1) runs commandlines with /bin/sh anyway, which resolves paths. No need to do it ourselves. --- debian/bin/restart.sh | 4 ++-- fedora/restart.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'debian/bin') diff --git a/debian/bin/restart.sh b/debian/bin/restart.sh index acbec3dc7..46a70c497 100755 --- a/debian/bin/restart.sh +++ b/debian/bin/restart.sh @@ -37,10 +37,10 @@ fi echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 0.5; /usr/bin/sudo $( which systemctl ) start jellyfin" | at now + echo "sleep 0.5; /usr/bin/sudo systemctl start jellyfin" | at now ;; 'service') - echo "sleep 0.5; /usr/bin/sudo $( which service ) jellyfin start" | at now + echo "sleep 0.5; /usr/bin/sudo service jellyfin start" | at now ;; 'sysv') echo "sleep 0.5; /usr/bin/sudo /etc/init.d/jellyfin start" | at now diff --git a/fedora/restart.sh b/fedora/restart.sh index acbec3dc7..46a70c497 100755 --- a/fedora/restart.sh +++ b/fedora/restart.sh @@ -37,10 +37,10 @@ fi echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 0.5; /usr/bin/sudo $( which systemctl ) start jellyfin" | at now + echo "sleep 0.5; /usr/bin/sudo systemctl start jellyfin" | at now ;; 'service') - echo "sleep 0.5; /usr/bin/sudo $( which service ) jellyfin start" | at now + echo "sleep 0.5; /usr/bin/sudo service jellyfin start" | at now ;; 'sysv') echo "sleep 0.5; /usr/bin/sudo /etc/init.d/jellyfin start" | at now -- cgit v1.2.3 From 2911dfc37d79bb4069a0ca1272ee6609f0400a39 Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Sun, 29 Nov 2020 03:48:56 -0500 Subject: Don't restart with sudo(8) if it's not available Some environments, like system containers, have no reason to have sudo(8) installed. In these environments restart.sh will silently fail because /usr/bin/sudo does not exist to execute, so test that sudo exists and don't try to use it otherwise. Note also that hardcoding sudo's path is wrong: it can be installed in other places. On FreeBSD, for example, it is /usr/local/bin/sudo when installed from ports. --- debian/bin/restart.sh | 10 ++++++++-- fedora/restart.sh | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'debian/bin') diff --git a/debian/bin/restart.sh b/debian/bin/restart.sh index 46a70c497..6aea24ee4 100755 --- a/debian/bin/restart.sh +++ b/debian/bin/restart.sh @@ -34,13 +34,19 @@ else fi fi +if type sudo >/dev/null 2>&1; then + sudo_command=sudo +else + sudo_command= +fi + echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 0.5; /usr/bin/sudo systemctl start jellyfin" | at now + echo "sleep 0.5; $sudo_command systemctl start jellyfin" | at now ;; 'service') - echo "sleep 0.5; /usr/bin/sudo service jellyfin start" | at now + echo "sleep 0.5; $sudo_command service jellyfin start" | at now ;; 'sysv') echo "sleep 0.5; /usr/bin/sudo /etc/init.d/jellyfin start" | at now diff --git a/fedora/restart.sh b/fedora/restart.sh index 46a70c497..6aea24ee4 100755 --- a/fedora/restart.sh +++ b/fedora/restart.sh @@ -34,13 +34,19 @@ else fi fi +if type sudo >/dev/null 2>&1; then + sudo_command=sudo +else + sudo_command= +fi + echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 0.5; /usr/bin/sudo systemctl start jellyfin" | at now + echo "sleep 0.5; $sudo_command systemctl start jellyfin" | at now ;; 'service') - echo "sleep 0.5; /usr/bin/sudo service jellyfin start" | at now + echo "sleep 0.5; $sudo_command service jellyfin start" | at now ;; 'sysv') echo "sleep 0.5; /usr/bin/sudo /etc/init.d/jellyfin start" | at now -- cgit v1.2.3 From d251c701b940fc1d7d1f29799785d4bc290b8ce6 Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Sun, 29 Nov 2020 04:35:22 -0500 Subject: Use systemd-run(1) in restart.sh systemd-run(1) runs `systemctl restart` in an isolated systemd unit that is not subject to process termination as jellyfin.service is shut down. We adjust the sudoers configuration for this new usage, removing the old config, since restart.sh is the only user of the sudoers policy. Additionally we change `systemctl start` to `systemctl restart` since there was a race condition where jellyfin.service was not fully stopped by the time this ran, so `systemctl start` became a noop. `systemctl restart` on the other hand works whether jellyfin.service is stopped or not. The at(1) hack (and the usage of `start` instead of `restart`) is left in for other init systems since I cannot test on those systems, and because I don't know of any systemd-run(1) equivalent (although it may be a non-issue since alternate init systems do not keep track of daemon children nearly as aggressively as systemd does). --- debian/bin/restart.sh | 3 ++- debian/conf/jellyfin-sudoers | 6 +++--- fedora/jellyfin.sudoers | 7 +++---- fedora/restart.sh | 3 ++- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'debian/bin') diff --git a/debian/bin/restart.sh b/debian/bin/restart.sh index 6aea24ee4..be5ca2c8b 100755 --- a/debian/bin/restart.sh +++ b/debian/bin/restart.sh @@ -43,7 +43,8 @@ fi echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 0.5; $sudo_command systemctl start jellyfin" | at now + # Without systemd-run here, `jellyfin.service`'s shutdown terminates this process too + $sudo_command systemd-run --scope systemctl restart jellyfin ;; 'service') echo "sleep 0.5; $sudo_command service jellyfin start" | at now diff --git a/debian/conf/jellyfin-sudoers b/debian/conf/jellyfin-sudoers index b481ba4ad..01e90322b 100644 --- a/debian/conf/jellyfin-sudoers +++ b/debian/conf/jellyfin-sudoers @@ -2,9 +2,9 @@ Cmnd_Alias RESTARTSERVER_SYSV = /sbin/service jellyfin restart, /usr/sbin/service jellyfin restart Cmnd_Alias STARTSERVER_SYSV = /sbin/service jellyfin start, /usr/sbin/service jellyfin start Cmnd_Alias STOPSERVER_SYSV = /sbin/service jellyfin stop, /usr/sbin/service jellyfin stop -Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemctl restart jellyfin, /bin/systemctl restart jellyfin -Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemctl start jellyfin, /bin/systemctl start jellyfin -Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemctl stop jellyfin, /bin/systemctl stop jellyfin +Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl restart jellyfin +Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl start jellyfin +Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl stop jellyfin Cmnd_Alias RESTARTSERVER_INITD = /etc/init.d/jellyfin restart Cmnd_Alias STARTSERVER_INITD = /etc/init.d/jellyfin start Cmnd_Alias STOPSERVER_INITD = /etc/init.d/jellyfin stop diff --git a/fedora/jellyfin.sudoers b/fedora/jellyfin.sudoers index dd245af4b..5a7054e99 100644 --- a/fedora/jellyfin.sudoers +++ b/fedora/jellyfin.sudoers @@ -1,8 +1,7 @@ # Allow jellyfin group to start, stop and restart itself -Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemctl restart jellyfin, /bin/systemctl restart jellyfin -Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemctl start jellyfin, /bin/systemctl start jellyfin -Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemctl stop jellyfin, /bin/systemctl stop jellyfin - +Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl restart jellyfin +Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl start jellyfin +Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl stop jellyfin jellyfin ALL=(ALL) NOPASSWD: RESTARTSERVER_SYSTEMD jellyfin ALL=(ALL) NOPASSWD: STARTSERVER_SYSTEMD diff --git a/fedora/restart.sh b/fedora/restart.sh index 6aea24ee4..be5ca2c8b 100755 --- a/fedora/restart.sh +++ b/fedora/restart.sh @@ -43,7 +43,8 @@ fi echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') - echo "sleep 0.5; $sudo_command systemctl start jellyfin" | at now + # Without systemd-run here, `jellyfin.service`'s shutdown terminates this process too + $sudo_command systemd-run --scope systemctl restart jellyfin ;; 'service') echo "sleep 0.5; $sudo_command service jellyfin start" | at now -- cgit v1.2.3 From bab389114b5833735d55d982ba1a2c17fd22e0d2 Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Fri, 4 Dec 2020 16:08:49 -0800 Subject: Use a service unit, not a scope unit, to restart Reportedly `systemd-run --scope` still got killed by the service manager; see #4615. The suspected cause is that `scope` units are run by the `systemd-run` process itself and inherit the caller's execution environment (see systemd-run(1)). To fix this, we use a systemd `service` unit instead, which is run and managed by PID 1 - hopefully this will isolate us sufficiently so that we don't get terminated along with `jellyfin.service`. --- debian/bin/restart.sh | 2 +- debian/conf/jellyfin-sudoers | 6 +++--- fedora/jellyfin.sudoers | 6 +++--- fedora/restart.sh | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'debian/bin') diff --git a/debian/bin/restart.sh b/debian/bin/restart.sh index be5ca2c8b..4847b918b 100755 --- a/debian/bin/restart.sh +++ b/debian/bin/restart.sh @@ -44,7 +44,7 @@ echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') # Without systemd-run here, `jellyfin.service`'s shutdown terminates this process too - $sudo_command systemd-run --scope systemctl restart jellyfin + $sudo_command systemd-run systemctl restart jellyfin ;; 'service') echo "sleep 0.5; $sudo_command service jellyfin start" | at now diff --git a/debian/conf/jellyfin-sudoers b/debian/conf/jellyfin-sudoers index 01e90322b..f84e7454f 100644 --- a/debian/conf/jellyfin-sudoers +++ b/debian/conf/jellyfin-sudoers @@ -2,9 +2,9 @@ Cmnd_Alias RESTARTSERVER_SYSV = /sbin/service jellyfin restart, /usr/sbin/service jellyfin restart Cmnd_Alias STARTSERVER_SYSV = /sbin/service jellyfin start, /usr/sbin/service jellyfin start Cmnd_Alias STOPSERVER_SYSV = /sbin/service jellyfin stop, /usr/sbin/service jellyfin stop -Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl restart jellyfin -Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl start jellyfin -Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl stop jellyfin +Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run systemctl restart jellyfin +Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run systemctl start jellyfin +Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run systemctl stop jellyfin Cmnd_Alias RESTARTSERVER_INITD = /etc/init.d/jellyfin restart Cmnd_Alias STARTSERVER_INITD = /etc/init.d/jellyfin start Cmnd_Alias STOPSERVER_INITD = /etc/init.d/jellyfin stop diff --git a/fedora/jellyfin.sudoers b/fedora/jellyfin.sudoers index 5a7054e99..57a9e7b67 100644 --- a/fedora/jellyfin.sudoers +++ b/fedora/jellyfin.sudoers @@ -1,7 +1,7 @@ # Allow jellyfin group to start, stop and restart itself -Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl restart jellyfin -Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl start jellyfin -Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run --scope systemctl stop jellyfin +Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run systemctl restart jellyfin +Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run systemctl start jellyfin +Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run systemctl stop jellyfin jellyfin ALL=(ALL) NOPASSWD: RESTARTSERVER_SYSTEMD jellyfin ALL=(ALL) NOPASSWD: STARTSERVER_SYSTEMD diff --git a/fedora/restart.sh b/fedora/restart.sh index be5ca2c8b..4847b918b 100755 --- a/fedora/restart.sh +++ b/fedora/restart.sh @@ -44,7 +44,7 @@ echo "Detected service control platform '$cmd'; using it to restart Jellyfin..." case $cmd in 'systemctl') # Without systemd-run here, `jellyfin.service`'s shutdown terminates this process too - $sudo_command systemd-run --scope systemctl restart jellyfin + $sudo_command systemd-run systemctl restart jellyfin ;; 'service') echo "sleep 0.5; $sudo_command service jellyfin start" | at now -- cgit v1.2.3