mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 23:03:40 +01:00
switch-to-configuration: Stop sockets corresponding to services
If a service has a corresponding socket unit, then stop the socket before stopping the service. This prevents it from being restarted behind our backs. Also, don't restart the service; it will be restarted on demand via the socket.
This commit is contained in:
parent
e194d41b9c
commit
8adc1ee92e
1 changed files with 42 additions and 14 deletions
|
@ -91,23 +91,27 @@ sub boolIsTrue {
|
|||
return $s eq "yes" || $s eq "true";
|
||||
}
|
||||
|
||||
# Forget about previously failed services.
|
||||
system("@systemd@/bin/systemctl", "reset-failed");
|
||||
|
||||
# Stop all services that no longer exist or have changed in the new
|
||||
# configuration.
|
||||
my (@unitsToStop, @unitsToSkip);
|
||||
my $activePrev = getActiveUnits;
|
||||
while (my ($unit, $state) = each %{$activePrev}) {
|
||||
my $baseUnit = $unit;
|
||||
|
||||
# Recognise template instances.
|
||||
$baseUnit = "$1\@.$2" if $unit =~ /^(.*)@[^\.]*\.(.*)$/;
|
||||
my $prevUnitFile = "/etc/systemd/system/$baseUnit";
|
||||
my $newUnitFile = "@out@/etc/systemd/system/$baseUnit";
|
||||
|
||||
my $baseName = $baseUnit;
|
||||
$baseName =~ s/\.[a-z]*$//;
|
||||
|
||||
if (-e $prevUnitFile && ($state->{state} eq "active" || $state->{state} eq "activating")) {
|
||||
if (! -e $newUnitFile) {
|
||||
push @unitsToStop, $unit;
|
||||
} elsif ($unit =~ /\.target$/) {
|
||||
}
|
||||
|
||||
elsif ($unit =~ /\.target$/) {
|
||||
# Cause all active target units to be restarted below.
|
||||
# This should start most changed units we stop here as
|
||||
# well as any new dependencies (including new mounts and
|
||||
|
@ -120,7 +124,9 @@ while (my ($unit, $state) = each %{$activePrev}) {
|
|||
write_file($restartListFile, { append => 1 }, "$unit\n");
|
||||
}
|
||||
}
|
||||
} elsif (abs_path($prevUnitFile) ne abs_path($newUnitFile)) {
|
||||
}
|
||||
|
||||
elsif (abs_path($prevUnitFile) ne abs_path($newUnitFile)) {
|
||||
if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target") {
|
||||
# Do nothing. These cannot be restarted directly.
|
||||
} elsif ($unit =~ /\.mount$/) {
|
||||
|
@ -131,14 +137,26 @@ while (my ($unit, $state) = each %{$activePrev}) {
|
|||
} else {
|
||||
my $unitInfo = parseUnit($newUnitFile);
|
||||
if (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "true")
|
||||
|| $unit eq "systemd-user-sessions.service")
|
||||
|| $unit eq "systemd-user-sessions.service"
|
||||
|| $unit eq "systemd-journald.service")
|
||||
{
|
||||
push @unitsToSkip, $unit;
|
||||
} else {
|
||||
# If this unit has a corresponding socket unit,
|
||||
# then stop the socket unit as well, and restart
|
||||
# the socket instead of the service.
|
||||
if ($unit =~ /\.service$/ && defined $activePrev->{"$baseName.socket"}) {
|
||||
push @unitsToStop, "$baseName.socket";
|
||||
write_file($restartListFile, { append => 1 }, "$baseName.socket\n");
|
||||
}
|
||||
|
||||
# Record that this unit needs to be started below. We
|
||||
# write this to a file to ensure that the service gets
|
||||
# restarted if we're interrupted.
|
||||
write_file($restartListFile, { append => 1 }, "$unit\n");
|
||||
else {
|
||||
write_file($restartListFile, { append => 1 }, "$unit\n");
|
||||
}
|
||||
|
||||
push @unitsToStop, $unit;
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +174,17 @@ sub pathToUnitName {
|
|||
return $path;
|
||||
}
|
||||
|
||||
sub unique {
|
||||
my %seen;
|
||||
my @res;
|
||||
foreach my $name (@_) {
|
||||
next if $seen{$name};
|
||||
$seen{$name} = 1;
|
||||
push @res, $name;
|
||||
}
|
||||
return @res;
|
||||
}
|
||||
|
||||
# Compare the previous and new fstab to figure out which filesystems
|
||||
# need a remount or need to be unmounted. New filesystems are mounted
|
||||
# automatically by starting local-fs.target. Also handles swap
|
||||
|
@ -189,6 +218,7 @@ foreach my $mountPoint (keys %prevFstab) {
|
|||
}
|
||||
|
||||
if (scalar @unitsToStop > 0) {
|
||||
@unitsToStop = unique(@unitsToStop);
|
||||
print STDERR "stopping the following units: ", join(", ", sort(@unitsToStop)), "\n";
|
||||
system("@systemd@/bin/systemctl", "stop", "--", @unitsToStop); # FIXME: ignore errors?
|
||||
}
|
||||
|
@ -204,14 +234,12 @@ system("@out@/activate", "@out@") == 0 or $res = 2;
|
|||
|
||||
# FIXME: Re-exec systemd if necessary.
|
||||
|
||||
# Forget about previously failed services.
|
||||
system("@systemd@/bin/systemctl", "reset-failed");
|
||||
|
||||
# Make systemd reload its units.
|
||||
system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3;
|
||||
|
||||
sub unique {
|
||||
my %unique = map { $_, 1 } @_;
|
||||
return sort(keys(%unique));
|
||||
}
|
||||
|
||||
# Start all active targets, as well as changed units we stopped above.
|
||||
# The latter is necessary because some may not be dependencies of the
|
||||
# targets (i.e., they were manually started). FIXME: detect units
|
||||
|
@ -219,7 +247,7 @@ sub unique {
|
|||
# same time because we'll get a "Failed to add path to set" error from
|
||||
# systemd.
|
||||
my @start = unique("default.target", split('\n', read_file($restartListFile, err_mode => 'quiet') // ""));
|
||||
print STDERR "starting the following units: ", join(", ", @start), "\n";
|
||||
print STDERR "starting the following units: ", join(", ", sort(@start)), "\n";
|
||||
system("@systemd@/bin/systemctl", "start", "--", @start) == 0 or $res = 4;
|
||||
unlink($restartListFile);
|
||||
|
||||
|
@ -227,7 +255,7 @@ unlink($restartListFile);
|
|||
# units.
|
||||
my @reload = unique(split '\n', read_file($reloadListFile, err_mode => 'quiet') // "");
|
||||
if (scalar @reload > 0) {
|
||||
print STDERR "reloading the following units: ", join(", ", @reload), "\n";
|
||||
print STDERR "reloading the following units: ", join(", ", sort(@reload)), "\n";
|
||||
system("@systemd@/bin/systemctl", "reload", "--", @reload) == 0 or $res = 4;
|
||||
unlink($reloadListFile);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue