Package: sysv-rc Version: 2.88dsf-22.1 Severity: wishlist Tags: patch Just like invoke-rc.d and update-rc.d can properly deal with a system using upstart, it should support systemd as well.
The attached patches make invoke-rc.d and update-rc.d systemd aware. This means that the enable/disable action of update-rc.d additionally create the appropriate links for systemd (regardless of whether you are running systemd or not). This will lead to users of sysvinit being able to switch to systemd (and vice-versa) and still get the same set of services started at boot. Roger Leigh reviewed this patches and gave me a few valuable hints, thanks for that. It would be great if you could upload a new version of sysv-rc to experimental which contains these patches. That’d be helpful to work on other aspects of systemd packaging in Debian. Best regards, Michael
--- /usr/sbin/invoke-rc.d.O 2012-07-20 14:58:14.140223575 +0200 +++ /usr/sbin/invoke-rc.d 2012-07-28 15:53:26.969445300 +0200 @@ -38,6 +38,7 @@ RETURNFAILURE= RC= is_upstart= +is_systemd= # Shell options set +e @@ -273,6 +274,8 @@ && [ -e "$UPSTARTDIR/${INITSCRIPTID}.conf" ] then is_upstart=1 +elif test -e /sys/fs/cgroup/systemd ; then + is_systemd=1 elif test ! -f "${INITDPREFIX}${INITSCRIPTID}" ; then ## Verifies if the given initscript ID is known ## For sysvinit, this error is critical @@ -383,7 +386,18 @@ esac # test if /etc/init.d/initscript is actually executable -if [ -n "$is_upstart" ] || testexec "${INITDPREFIX}${INITSCRIPTID}" ; then +_executable= +if [ -n "$is_upstart" ]; then + _executable=1 +elif [ -n "$is_systemd" ]; then + _state=$(systemctl -p LoadState show "${INITSCRIPTID}.service" 2>/dev/null) + if [ "$_state" != "LoadState=masked" ]; then + _executable=1 + fi +elif testexec "${INITDPREFIX}${INITSCRIPTID}"; then + _executable=1 +fi +if [ "$_executable" = "1" ]; then if test x${RC} = x && test x${MODE} = xquery ; then RC=105 fi @@ -496,6 +510,31 @@ initctl "$saction" "$INITSCRIPTID" && exit 0 ;; esac + elif [ -n "$is_systemd" ]; then + case $saction in + start|stop|restart|status) + systemctl "${saction}" "${INITSCRIPTID}.service" && exit 0 + ;; + reload) + _canreload="$(systemctl -p CanReload show $service 2>/dev/null)" + if [ "$_canreload" = "CanReload=no" ]; then + "${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0 + else + systemctl reload "${INITSCRIPTID}.service" && exit 0 + fi + ;; + force-stop) + systemctl --signal=KILL kill "${INITSCRIPTID}.service" && exit 0 + ;; + force-reload) + systemctl restart "${INITSCRIPTID}.service" && exit 0 + ;; + *) + # We try to run non-standard actions by running + # the init script directly. + "${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0 + ;; + esac else "${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0 fi
--- /usr/sbin/update-rc.d.O 2012-07-20 16:48:26.446152769 +0200 +++ /usr/sbin/update-rc.d 2012-07-21 10:55:41.408503038 +0200 @@ -5,6 +5,7 @@ use strict; use warnings; +use File::Path qw(make_path); # in core since Perl 5.001 my $initd = "/etc/init.d"; my $etcd = "/etc/rc"; @@ -424,6 +425,42 @@ error("initscript does not exist: /etc/init.d/$scriptname"); } } elsif ("disable" eq $action || "enable" eq $action) { + # In addition to the insserv call we also enable/disable the service + # for systemd by creating the appropriate symlink in case there is a + # native systemd service. We need to do this on our own instead of + # using systemctl because systemd might not even be installed yet. + my $service_path; + if (-f "/etc/systemd/system/$scriptname.service") { + $service_path = "/etc/systemd/system/$scriptname.service"; + } elsif (-f "/lib/systemd/system/$scriptname.service") { + $service_path = "/lib/systemd/system/$scriptname.service"; + } + if (defined($service_path)) { + my $changed_sth; + open my $fh, '<', $service_path or error("unable to read $service_path"); + while (<$fh>) { + chomp; + if (/^\s*WantedBy=(.+)$/i) { + my $wants_dir = "/etc/systemd/system/$1.wants"; + my $service_link = "$wants_dir/$scriptname.service"; + if ("enable" eq $action) { + make_path($wants_dir); + symlink($service_path, $service_link); + } else { + unlink($service_link) if -e $service_link; + } + $changed_sth = 1; + } + } + close($fh); + + # If we changed anything and this machine is running systemd, tell + # systemd to reload so that it will immediately pick up our + # changes. + if ($changed_sth && -e "/sys/fs/cgroup/systemd") { + system("systemctl", "daemon-reload"); + } + } insserv_toggle($notreally, $action, $scriptname, @args); # Call insserv to resequence modified links my $rc = system("insserv", @opts, $scriptname) >> 8;