Control: severity -1 important Control: tags -1 + patch
Dear Maintainer, (Cc systemd maintainers, because it's of interest to them.) I have created a patch that implements the previously missing parts of systemd integration into update-rc.d, following along the lines of the patch I have written for deb-systemd-helper (bug #780522). The patch now makes update-rc.d support: - drop-in configuration snippets - multiple words per setting (i.e. "WantedBy=a b") - RequiredBy=, Alias=, Also= (Note that the patch currently implements the full systemd logic of also looking at /run/systemd/generator*, which may or may not be something one wants or not - I would defer to the systemd team as to whether they'd want to see that included - but it should be consistent across update-rc.d and deb-systemd-helper.) Since systemctl enable/disable calls out to update-rc.d, I think this is something that should definitely be fixed for Jessie (otherwise, doing systemctl (en|dis)able something-with-alias.service will not work properly!). I have diverted update-rc.d on my local machine and replaced it with the patched version. I've also tested it with some examples and as far as I can tell it works properly. Christian
diff -Nru sysvinit-2.88dsf/debian/src/sysv-rc/sbin/update-rc.d sysvinit-2.88dsf/debian/src/sysv-rc/sbin/update-rc.d --- sysvinit-2.88dsf/debian/src/sysv-rc/sbin/update-rc.d 2014-10-25 23:15:12.000000000 +0200 +++ sysvinit-2.88dsf/debian/src/sysv-rc/sbin/update-rc.d 2015-03-15 15:49:27.000000000 +0100 @@ -7,6 +7,7 @@ use warnings; # NB: All Perl modules used here must be in perl-base. Specifically, depending # on modules in perl-modules is not okay! See bug #716923 +use Text::ParseWords qw(shellwords); # in core since Perl 5 my $initd = "/etc/init.d"; my $etcd = "/etc/rc"; @@ -63,46 +64,121 @@ map { push @dirs, $_; mkdir join('/', @dirs), 0755; } @path; } +# Recursively deletes a directory structure, if all (!) components are empty, +# e.g. to clean up after purging. +# (Taken from deb-systemd-helper) +sub rmdir_if_empty { + my ($dir) = @_; + + rmdir_if_empty($_) for (grep { -d } <$dir/*>); + rmdir($dir); +} + # Creates the necessary links to enable/disable the service (equivalent of an # initscript) in systemd. sub make_systemd_links { - my ($scriptname, $action) = @_; + my ($scriptname, $action, $recursive) = @_; + + my @unit_paths = ( + "/run/systemd/generator.late", + "/lib/systemd/system", + "/run/systemd/generator", + "/etc/systemd/system", + "/run/systemd/generator.early" + ); # 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); + + # The following code is adapted from deb-systemd-helper + my ($service_path, %dropins); + + foreach (@unit_paths) { + if (-f "$_/$scriptname") { + $service_path = "$_/$scriptname"; + } + foreach (<$_/$scriptname.d/*.conf>) { + $dropins{basename($_)} = $_; + } + } + + return unless defined($service_path); + + my $changed_sth = 0; + my $unit_config = { + 'WantedBy' => [], + 'RequiredBy' => [], + 'Also' => [], + 'Alias' => [] + }; + + foreach ($service_path, sort values %dropins) { + open my $fh, '<', $_ or error("unable to read $_"); + while (my $line = <$fh>) { + chomp($line); + if ($line =~ /^\s*(WantedBy|RequiredBy|Also|Alias)=(.*)$/i) { + my @values = shellwords($2); + + # systemd will reset a list to empty if it encounters an + # empty value + if (scalar (@values) == 0) { + $unit_config->{$1} = []; } else { - unlink($service_link) if -e $service_link; + push(@{$unit_config->{$1}}, @values); } - $changed_sth = 1; } } close($fh); + } + + for my $value (@{$unit_config->{'WantedBy'}}) { + my $wants_dir = "/etc/systemd/system/$value.wants"; + my $service_link = "$wants_dir/$scriptname"; + if ("enable" eq $action) { + make_path($wants_dir); + symlink($service_path, $service_link); + } else { + unlink($service_link) if -e $service_link; + rmdir_if_empty($wants_dir); + } + $changed_sth = 1; + } + + for my $value (@{$unit_config->{'RequiredBy'}}) { + my $requires_dir = "/etc/systemd/system/$value.requires"; + my $service_link = "$requires_dir/$scriptname"; + if ("enable" eq $action) { + make_path($requires_dir); + symlink($service_path, $service_link); + } else { + unlink($service_link) if -e $service_link; + rmdir_if_empty($requires_dir); + } + $changed_sth = 1; + } - # 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 && -d "/run/systemd/system") { - system("systemctl", "daemon-reload"); + for my $value (@{$unit_config->{'Alias'}}) { + my $link = "/etc/systemd/system/$value"; + if ("enable" eq $action) { + symlink($service_path, $link); + } else { + unlink($link) if -e $link; } + $changed_sth = 1; + } + + for my $value (@{$unit_config->{'Also'}}) { + make_systemd_links($value, $action, 1); + $changed_sth = 1; + } + + # If we changed anything and this machine is running systemd, tell + # systemd to reload so that it will immediately pick up our + # changes. Only do this if we aren't calling ourselves recursively. + if (!$recursive && $changed_sth && -d "/run/systemd/system") { + system("systemctl", "daemon-reload"); } } @@ -213,7 +289,9 @@ error("initscript does not exist: /etc/init.d/$scriptname"); } } elsif ("disable" eq $action || "enable" eq $action) { - make_systemd_links($scriptname, $action); + # add .service suffix here because make_systemd_links must + # be able to call itself recursively for Also= in units + make_systemd_links("$scriptname.service", $action, 0); upstart_toggle($scriptname, $action);
_______________________________________________ Pkg-systemd-maintainers mailing list Pkg-systemd-maintainers@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-systemd-maintainers