nixos/switch-to-configuration: Use parenthesis on all calls

This commit is contained in:
Janne Heß 2022-03-10 12:54:59 +01:00
parent bc58430068
commit 461c1c9e86
No known key found for this signature in database
GPG key ID: 69165158F05265DF

View file

@ -10,6 +10,8 @@ use Net::DBus;
use Sys::Syslog qw(:standard :macros); use Sys::Syslog qw(:standard :macros);
use Cwd 'abs_path'; use Cwd 'abs_path';
## no critic(CodeLayout::ProhibitParensWithBuiltins)
my $out = "@out@"; my $out = "@out@";
my $curSystemd = abs_path("/run/current-system/sw/bin"); my $curSystemd = abs_path("/run/current-system/sw/bin");
@ -36,13 +38,13 @@ my $dryReloadByActivationFile = "/run/nixos/dry-activation-reload-list";
make_path("/run/nixos", { mode => oct(755) }); make_path("/run/nixos", { mode => oct(755) });
my $action = shift @ARGV; my $action = shift(@ARGV);
if ("@localeArchive@" ne "") { if ("@localeArchive@" ne "") {
$ENV{LOCALE_ARCHIVE} = "@localeArchive@"; $ENV{LOCALE_ARCHIVE} = "@localeArchive@";
} }
if (!defined $action || ($action ne "switch" && $action ne "boot" && $action ne "test" && $action ne "dry-activate")) { if (!defined($action) || ($action ne "switch" && $action ne "boot" && $action ne "test" && $action ne "dry-activate")) {
print STDERR <<EOF; print STDERR <<EOF;
Usage: $0 [switch|boot|test] Usage: $0 [switch|boot|test]
@ -51,27 +53,27 @@ boot: make the configuration the boot default
test: activate the configuration, but don\'t make it the boot default test: activate the configuration, but don\'t make it the boot default
dry-activate: show what would be done if this configuration were activated dry-activate: show what would be done if this configuration were activated
EOF EOF
exit 1; exit(1);
} }
$ENV{NIXOS_ACTION} = $action; $ENV{NIXOS_ACTION} = $action;
# This is a NixOS installation if it has /etc/NIXOS or a proper # This is a NixOS installation if it has /etc/NIXOS or a proper
# /etc/os-release. # /etc/os-release.
die "This is not a NixOS installation!\n" unless die("This is not a NixOS installation!\n") unless
-f "/etc/NIXOS" || (read_file("/etc/os-release", err_mode => 'quiet') // "") =~ /ID="?nixos"?/s; -f "/etc/NIXOS" || (read_file("/etc/os-release", err_mode => 'quiet') // "") =~ /ID="?nixos"?/s;
openlog("nixos", "", LOG_USER); openlog("nixos", "", LOG_USER);
# Install or update the bootloader. # Install or update the bootloader.
if ($action eq "switch" || $action eq "boot") { if ($action eq "switch" || $action eq "boot") {
system("@installBootLoader@ $out") == 0 or exit 1; system('@installBootLoader@', $out) == 0 or exit 1;
} }
# Just in case the new configuration hangs the system, do a sync now. # Just in case the new configuration hangs the system, do a sync now.
system("@coreutils@/bin/sync", "-f", "/nix/store") unless ($ENV{"NIXOS_NO_SYNC"} // "") eq "1"; system("@coreutils@/bin/sync", "-f", "/nix/store") unless ($ENV{"NIXOS_NO_SYNC"} // "") eq "1";
exit 0 if $action eq "boot"; exit(0) if $action eq "boot";
# Check if we can activate the new configuration. # Check if we can activate the new configuration.
my $oldVersion = read_file("/run/current-system/init-interface-version", err_mode => 'quiet') // ""; my $oldVersion = read_file("/run/current-system/init-interface-version", err_mode => 'quiet') // "";
@ -83,7 +85,7 @@ Warning: the new NixOS configuration has an init that is
incompatible with the current configuration. The new configuration incompatible with the current configuration. The new configuration
won\'t take effect until you reboot the system. won\'t take effect until you reboot the system.
EOF EOF
exit 100; exit(100);
} }
# Ignore SIGHUP so that we're not killed if we're running on (say) # Ignore SIGHUP so that we're not killed if we're running on (say)
@ -110,7 +112,7 @@ sub unit_is_active {
my $mgr = Net::DBus->system->get_service('org.freedesktop.systemd1')->get_object('/org/freedesktop/systemd1'); my $mgr = Net::DBus->system->get_service('org.freedesktop.systemd1')->get_object('/org/freedesktop/systemd1');
my $units = $mgr->ListUnitsByNames([$unit_name]); my $units = $mgr->ListUnitsByNames([$unit_name]);
if (@{$units} == 0) { if (scalar(@{$units}) == 0) {
return 0; return 0;
} }
my $active_state = $units->[0]->[3]; ## no critic (ValuesAndExpressions::ProhibitMagicNumbers) my $active_state = $units->[0]->[3]; ## no critic (ValuesAndExpressions::ProhibitMagicNumbers)
@ -121,10 +123,10 @@ sub parseFstab {
my ($filename) = @_; my ($filename) = @_;
my ($fss, $swaps); my ($fss, $swaps);
foreach my $line (read_file($filename, err_mode => 'quiet')) { foreach my $line (read_file($filename, err_mode => 'quiet')) {
chomp $line; chomp($line);
$line =~ s/^\s*#.*//; $line =~ s/^\s*#.*//;
next if $line =~ /^\s*$/; next if $line =~ /^\s*$/;
my @xs = split / /, $line; my @xs = split(/ /, $line);
if ($xs[2] eq "swap") { if ($xs[2] eq "swap") {
$swaps->{$xs[0]} = { options => $xs[3] // "" }; $swaps->{$xs[0]} = { options => $xs[3] // "" };
} else { } else {
@ -146,17 +148,16 @@ sub parseFstab {
sub parseSystemdIni { sub parseSystemdIni {
my ($unitContents, $path) = @_; my ($unitContents, $path) = @_;
# Tie the ini file to a hash for easier access # Tie the ini file to a hash for easier access
my %fileContents; tie(my %fileContents, 'Config::IniFiles', (-file => $path, -allowempty => 1, -allowcontinue => 1)); ## no critic(Miscellanea::ProhibitTies)
tie %fileContents, "Config::IniFiles", (-file => $path, -allowempty => 1, -allowcontinue => 1);
# Copy over all sections # Copy over all sections
foreach my $sectionName (keys %fileContents) { foreach my $sectionName (keys(%fileContents)) {
if ($sectionName eq "Install") { if ($sectionName eq "Install") {
# Skip the [Install] section because it has no relevant keys for us # Skip the [Install] section because it has no relevant keys for us
next; next;
} }
# Copy over all keys # Copy over all keys
foreach my $iniKey (keys %{$fileContents{$sectionName}}) { foreach my $iniKey (keys(%{$fileContents{$sectionName}})) {
# Ensure the value is an array so it's easier to work with # Ensure the value is an array so it's easier to work with
my $iniValue = $fileContents{$sectionName}{$iniKey}; my $iniValue = $fileContents{$sectionName}{$iniKey};
my @iniValues; my @iniValues;
@ -194,7 +195,7 @@ sub parse_unit {
# Replace \ with \\ so glob() still works with units that have a \ in them # Replace \ with \\ so glob() still works with units that have a \ in them
# Valid characters in unit names are ASCII letters, digits, ":", "-", "_", ".", and "\" # Valid characters in unit names are ASCII letters, digits, ":", "-", "_", ".", and "\"
$unit_path =~ s/\\/\\\\/gmsx; $unit_path =~ s/\\/\\\\/gmsx;
foreach (glob "${unit_path}{,.d/*.conf}") { foreach (glob("${unit_path}{,.d/*.conf}")) {
parseSystemdIni(\%unit_data, "$_") parseSystemdIni(\%unit_data, "$_")
} }
return %unit_data; return %unit_data;
@ -207,7 +208,7 @@ sub parseSystemdBool {
my @values = @{$unitConfig->{$sectionName}{$boolName} // []}; my @values = @{$unitConfig->{$sectionName}{$boolName} // []};
# Return default if value is not set # Return default if value is not set
if (scalar @values lt 1 || not defined $values[-1]) { if (scalar(@values) lt 1 || not defined($values[-1])) {
return $default; return $default;
} }
# If value is defined multiple times, use the last definition # If value is defined multiple times, use the last definition
@ -224,7 +225,7 @@ sub recordUnit {
# The opposite of recordUnit, removes a unit name from a file # The opposite of recordUnit, removes a unit name from a file
sub unrecord_unit { sub unrecord_unit {
my ($fn, $unit) = @_; my ($fn, $unit) = @_;
edit_file { s/^$unit\n//msx } $fn if $action ne "dry-activate"; edit_file(sub { s/^$unit\n//msx }, $fn) if $action ne "dry-activate";
} }
# Compare the contents of two unit files and return whether the unit # Compare the contents of two unit files and return whether the unit
@ -252,20 +253,20 @@ sub compare_units {
my $comp_array = sub { my $comp_array = sub {
my ($a, $b) = @_; my ($a, $b) = @_;
return join("\0", @{$a}) eq join "\0", @{$b}; return join("\0", @{$a}) eq join("\0", @{$b});
}; };
# Comparison hash for the sections # Comparison hash for the sections
my %section_cmp = map { $_ => 1 } keys %{$new_unit}; my %section_cmp = map { $_ => 1 } keys(%{$new_unit});
# Iterate over the sections # Iterate over the sections
foreach my $section_name (keys %{$old_unit}) { foreach my $section_name (keys(%{$old_unit})) {
# Missing section in the new unit? # Missing section in the new unit?
if (not exists $section_cmp{$section_name}) { if (not exists($section_cmp{$section_name})) {
# If the [Unit] section was removed, make sure that only keys # If the [Unit] section was removed, make sure that only keys
# were in it that are ignored # were in it that are ignored
if ($section_name eq 'Unit') { if ($section_name eq 'Unit') {
foreach my $ini_key (keys %{$old_unit->{'Unit'}}) { foreach my $ini_key (keys(%{$old_unit->{'Unit'}})) {
if (not defined $unit_section_ignores{$ini_key}) { if (not defined($unit_section_ignores{$ini_key})) {
return 1; return 1;
} }
} }
@ -283,15 +284,15 @@ sub compare_units {
} }
delete $section_cmp{$section_name}; delete $section_cmp{$section_name};
# Comparison hash for the section contents # Comparison hash for the section contents
my %ini_cmp = map { $_ => 1 } keys %{$new_unit->{$section_name}}; my %ini_cmp = map { $_ => 1 } keys(%{$new_unit->{$section_name}});
# Iterate over the keys of the section # Iterate over the keys of the section
foreach my $ini_key (keys %{$old_unit->{$section_name}}) { foreach my $ini_key (keys(%{$old_unit->{$section_name}})) {
delete $ini_cmp{$ini_key}; delete $ini_cmp{$ini_key};
my @old_value = @{$old_unit->{$section_name}{$ini_key}}; my @old_value = @{$old_unit->{$section_name}{$ini_key}};
# If the key is missing in the new unit, they are different... # If the key is missing in the new unit, they are different...
if (not $new_unit->{$section_name}{$ini_key}) { if (not $new_unit->{$section_name}{$ini_key}) {
# ... unless the key that is now missing is one of the ignored keys # ... unless the key that is now missing is one of the ignored keys
if ($section_name eq 'Unit' and defined $unit_section_ignores{$ini_key}) { if ($section_name eq 'Unit' and defined($unit_section_ignores{$ini_key})) {
next; next;
} }
return 1; return 1;
@ -304,7 +305,7 @@ sub compare_units {
if ($ini_key eq 'X-Reload-Triggers') { if ($ini_key eq 'X-Reload-Triggers') {
$ret = 2; $ret = 2;
next; next;
} elsif (defined $unit_section_ignores{$ini_key}) { } elsif (defined($unit_section_ignores{$ini_key})) {
next; next;
} }
} }
@ -314,10 +315,10 @@ sub compare_units {
# A key was introduced that was missing in the old unit # A key was introduced that was missing in the old unit
if (%ini_cmp) { if (%ini_cmp) {
if ($section_name eq 'Unit') { if ($section_name eq 'Unit') {
foreach my $ini_key (keys %ini_cmp) { foreach my $ini_key (keys(%ini_cmp)) {
if ($ini_key eq 'X-Reload-Triggers') { if ($ini_key eq 'X-Reload-Triggers') {
$ret = 2; $ret = 2;
} elsif (defined $unit_section_ignores{$ini_key}) { } elsif (defined($unit_section_ignores{$ini_key})) {
next; next;
} else { } else {
return 1; return 1;
@ -330,9 +331,9 @@ sub compare_units {
} }
# A section was introduced that was missing in the old unit # A section was introduced that was missing in the old unit
if (%section_cmp) { if (%section_cmp) {
if (%section_cmp == 1 and defined $section_cmp{'Unit'}) { if (%section_cmp == 1 and defined($section_cmp{'Unit'})) {
foreach my $ini_key (keys %{$new_unit->{'Unit'}}) { foreach my $ini_key (keys(%{$new_unit->{'Unit'}})) {
if (not defined $unit_section_ignores{$ini_key}) { if (not defined($unit_section_ignores{$ini_key})) {
return 1; return 1;
} elsif ($ini_key eq 'X-Reload-Triggers') { } elsif ($ini_key eq 'X-Reload-Triggers') {
$ret = 2; $ret = 2;
@ -393,11 +394,11 @@ sub handleModifiedUnit {
my $socket_activated = 0; my $socket_activated = 0;
if ($unit =~ /\.service$/) { if ($unit =~ /\.service$/) {
my @sockets = split(/ /, join(" ", @{$unitInfo{Service}{Sockets} // []})); my @sockets = split(/ /, join(" ", @{$unitInfo{Service}{Sockets} // []}));
if (scalar @sockets == 0) { if (scalar(@sockets) == 0) {
@sockets = ("$baseName.socket"); @sockets = ("$baseName.socket");
} }
foreach my $socket (@sockets) { foreach my $socket (@sockets) {
if (defined $activePrev->{$socket}) { if (defined($activePrev->{$socket})) {
# We can now be sure this is a socket-activate unit # We can now be sure this is a socket-activate unit
$unitsToStop->{$socket} = 1; $unitsToStop->{$socket} = 1;
@ -459,8 +460,8 @@ $unitsToRestart{$_} = 1 foreach
$unitsToReload{$_} = 1 foreach $unitsToReload{$_} = 1 foreach
split('\n', read_file($reloadListFile, err_mode => 'quiet') // ""); split('\n', read_file($reloadListFile, err_mode => 'quiet') // "");
my $activePrev = getActiveUnits; my $activePrev = getActiveUnits();
while (my ($unit, $state) = each %{$activePrev}) { while (my ($unit, $state) = each(%{$activePrev})) {
my $baseUnit = $unit; my $baseUnit = $unit;
my $prevUnitFile = "/etc/systemd/system/$baseUnit"; my $prevUnitFile = "/etc/systemd/system/$baseUnit";
@ -520,9 +521,9 @@ while (my ($unit, $state) = each %{$activePrev}) {
my %old_unit_info = parse_unit($prevUnitFile); my %old_unit_info = parse_unit($prevUnitFile);
my %new_unit_info = parse_unit($newUnitFile); my %new_unit_info = parse_unit($newUnitFile);
my $diff = compare_units(\%old_unit_info, \%new_unit_info); my $diff = compare_units(\%old_unit_info, \%new_unit_info);
if ($diff eq 1) { if ($diff == 1) {
handleModifiedUnit($unit, $baseName, $newUnitFile, \%new_unit_info, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip); handleModifiedUnit($unit, $baseName, $newUnitFile, \%new_unit_info, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
} elsif ($diff eq 2 and not $unitsToRestart{$unit}) { } elsif ($diff == 2 and not $unitsToRestart{$unit}) {
$unitsToReload{$unit} = 1; $unitsToReload{$unit} = 1;
recordUnit($reloadListFile, $unit); recordUnit($reloadListFile, $unit);
} }
@ -533,11 +534,11 @@ while (my ($unit, $state) = each %{$activePrev}) {
sub pathToUnitName { sub pathToUnitName {
my ($path) = @_; my ($path) = @_;
# Use current version of systemctl binary before daemon is reexeced. # Use current version of systemctl binary before daemon is reexeced.
open my $cmd, "-|", "$curSystemd/systemd-escape", "--suffix=mount", "-p", $path open(my $cmd, "-|", "$curSystemd/systemd-escape", "--suffix=mount", "-p", $path)
or die "Unable to escape $path!\n"; or die "Unable to escape $path!\n";
my $escaped = join "", <$cmd>; my $escaped = join("", <$cmd>);
chomp $escaped; chomp($escaped);
close $cmd or die; close($cmd) or die('Unable to close systemd-escape pipe');
return $escaped; return $escaped;
} }
@ -546,13 +547,13 @@ sub pathToUnitName {
# automatically by starting local-fs.target. FIXME: might be nicer if # automatically by starting local-fs.target. FIXME: might be nicer if
# we generated units for all mounts; then we could unify this with the # we generated units for all mounts; then we could unify this with the
# unit checking code above. # unit checking code above.
my ($prevFss, $prevSwaps) = parseFstab "/etc/fstab"; my ($prevFss, $prevSwaps) = parseFstab("/etc/fstab");
my ($newFss, $newSwaps) = parseFstab "$out/etc/fstab"; my ($newFss, $newSwaps) = parseFstab("$out/etc/fstab");
foreach my $mountPoint (keys %$prevFss) { foreach my $mountPoint (keys(%$prevFss)) {
my $prev = $prevFss->{$mountPoint}; my $prev = $prevFss->{$mountPoint};
my $new = $newFss->{$mountPoint}; my $new = $newFss->{$mountPoint};
my $unit = pathToUnitName($mountPoint); my $unit = pathToUnitName($mountPoint);
if (!defined $new) { if (!defined($new)) {
# Filesystem entry disappeared, so unmount it. # Filesystem entry disappeared, so unmount it.
$unitsToStop{$unit} = 1; $unitsToStop{$unit} = 1;
} elsif ($prev->{fsType} ne $new->{fsType} || $prev->{device} ne $new->{device}) { } elsif ($prev->{fsType} ne $new->{fsType} || $prev->{device} ne $new->{device}) {
@ -568,10 +569,10 @@ foreach my $mountPoint (keys %$prevFss) {
} }
# Also handles swap devices. # Also handles swap devices.
foreach my $device (keys %$prevSwaps) { foreach my $device (keys(%$prevSwaps)) {
my $prev = $prevSwaps->{$device}; my $prev = $prevSwaps->{$device};
my $new = $newSwaps->{$device}; my $new = $newSwaps->{$device};
if (!defined $new) { if (!defined($new)) {
# Swap entry disappeared, so turn it off. Can't use # Swap entry disappeared, so turn it off. Can't use
# "systemctl stop" here because systemd has lots of alias # "systemctl stop" here because systemd has lots of alias
# units that prevent a stop from actually calling # units that prevent a stop from actually calling
@ -602,8 +603,8 @@ if ($prevSystemdSystemConfig ne $newSystemdSystemConfig) {
sub filterUnits { sub filterUnits {
my ($units) = @_; my ($units) = @_;
my @res; my @res;
foreach my $unit (sort(keys %{$units})) { foreach my $unit (sort(keys(%{$units}))) {
push @res, $unit if !defined $unitsToFilter{$unit}; push(@res, $unit) if !defined($unitsToFilter{$unit});
} }
return @res; return @res;
} }
@ -614,9 +615,9 @@ my @unitsToStopFiltered = filterUnits(\%unitsToStop);
# Show dry-run actions. # Show dry-run actions.
if ($action eq "dry-activate") { if ($action eq "dry-activate") {
print STDERR "would stop the following units: ", join(", ", @unitsToStopFiltered), "\n" print STDERR "would stop the following units: ", join(", ", @unitsToStopFiltered), "\n"
if scalar @unitsToStopFiltered > 0; if scalar(@unitsToStopFiltered) > 0;
print STDERR "would NOT stop the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n" print STDERR "would NOT stop the following changed units: ", join(", ", sort(keys(%unitsToSkip))), "\n"
if scalar(keys %unitsToSkip) > 0; if scalar(keys(%unitsToSkip)) > 0;
print STDERR "would activate the configuration...\n"; print STDERR "would activate the configuration...\n";
system("$out/dry-activate", "$out"); system("$out/dry-activate", "$out");
@ -637,7 +638,7 @@ if ($action eq "dry-activate") {
$baseName =~ s/\.[a-z]*$//; $baseName =~ s/\.[a-z]*$//;
# Start units if they were not active previously # Start units if they were not active previously
if (not defined $activePrev->{$unit}) { if (not defined($activePrev->{$unit})) {
$unitsToStart{$unit} = 1; $unitsToStart{$unit} = 1;
next; next;
} }
@ -657,28 +658,28 @@ if ($action eq "dry-activate") {
unlink($dryReloadByActivationFile); unlink($dryReloadByActivationFile);
print STDERR "would restart systemd\n" if $restartSystemd; print STDERR "would restart systemd\n" if $restartSystemd;
print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n" print STDERR "would reload the following units: ", join(", ", sort(keys(%unitsToReload))), "\n"
if scalar(keys %unitsToReload) > 0; if scalar(keys(%unitsToReload)) > 0;
print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n" print STDERR "would restart the following units: ", join(", ", sort(keys(%unitsToRestart))), "\n"
if scalar(keys %unitsToRestart) > 0; if scalar(keys(%unitsToRestart)) > 0;
my @unitsToStartFiltered = filterUnits(\%unitsToStart); my @unitsToStartFiltered = filterUnits(\%unitsToStart);
print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n" print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
if scalar @unitsToStartFiltered; if scalar(@unitsToStartFiltered);
exit 0; exit 0;
} }
syslog(LOG_NOTICE, "switching to system configuration $out"); syslog(LOG_NOTICE, "switching to system configuration $out");
if (scalar (keys %unitsToStop) > 0) { if (scalar(keys(%unitsToStop)) > 0) {
print STDERR "stopping the following units: ", join(", ", @unitsToStopFiltered), "\n" print STDERR "stopping the following units: ", join(", ", @unitsToStopFiltered), "\n"
if scalar @unitsToStopFiltered; if scalar(@unitsToStopFiltered);
# Use current version of systemctl binary before daemon is reexeced. # Use current version of systemctl binary before daemon is reexeced.
system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToStop)); system("$curSystemd/systemctl", "stop", "--", sort(keys(%unitsToStop)));
} }
print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n" print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys(%unitsToSkip))), "\n"
if scalar(keys %unitsToSkip) > 0; if scalar(keys(%unitsToSkip)) > 0;
# Activate the new configuration (i.e., update /etc, make accounts, # Activate the new configuration (i.e., update /etc, make accounts,
# and so on). # and so on).
@ -702,7 +703,7 @@ foreach (split('\n', read_file($restartByActivationFile, err_mode => 'quiet') //
$baseName =~ s/\.[a-z]*$//; $baseName =~ s/\.[a-z]*$//;
# Start units if they were not active previously # Start units if they were not active previously
if (not defined $activePrev->{$unit}) { if (not defined($activePrev->{$unit})) {
$unitsToStart{$unit} = 1; $unitsToStart{$unit} = 1;
recordUnit($startListFile, $unit); recordUnit($startListFile, $unit);
next; next;
@ -739,7 +740,7 @@ system("@systemd@/bin/systemctl", "reset-failed");
system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3; system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3;
# Reload user units # Reload user units
open my $listActiveUsers, '-|', '@systemd@/bin/loginctl', 'list-users', '--no-legend'; open(my $listActiveUsers, '-|', '@systemd@/bin/loginctl', 'list-users', '--no-legend');
while (my $f = <$listActiveUsers>) { while (my $f = <$listActiveUsers>) {
next unless $f =~ /^\s*(?<uid>\d+)\s+(?<user>\S+)/; next unless $f =~ /^\s*(?<uid>\d+)\s+(?<user>\S+)/;
my ($uid, $name) = ($+{uid}, $+{user}); my ($uid, $name) = ($+{uid}, $+{user});
@ -751,7 +752,7 @@ while (my $f = <$listActiveUsers>) {
"@systemd@/bin/systemctl --user start nixos-activation.service"); "@systemd@/bin/systemctl --user start nixos-activation.service");
} }
close $listActiveUsers; close($listActiveUsers);
# Set the new tmpfiles # Set the new tmpfiles
print STDERR "setting up tmpfiles\n"; print STDERR "setting up tmpfiles\n";
@ -760,8 +761,8 @@ system("@systemd@/bin/systemd-tmpfiles", "--create", "--remove", "--exclude-pref
# Before reloading we need to ensure that the units are still active. They may have been # Before reloading we need to ensure that the units are still active. They may have been
# deactivated because one of their requirements got stopped. If they are inactive # deactivated because one of their requirements got stopped. If they are inactive
# but should have been reloaded, the user probably expects them to be started. # but should have been reloaded, the user probably expects them to be started.
if (scalar(keys %unitsToReload) > 0) { if (scalar(keys(%unitsToReload)) > 0) {
for my $unit (keys %unitsToReload) { for my $unit (keys(%unitsToReload)) {
if (!unit_is_active($unit)) { if (!unit_is_active($unit)) {
# Figure out if we need to start the unit # Figure out if we need to start the unit
my %unit_info = parse_unit("$out/etc/systemd/system/$unit"); my %unit_info = parse_unit("$out/etc/systemd/system/$unit");
@ -777,17 +778,17 @@ if (scalar(keys %unitsToReload) > 0) {
} }
# Reload units that need it. This includes remounting changed mount # Reload units that need it. This includes remounting changed mount
# units. # units.
if (scalar(keys %unitsToReload) > 0) { if (scalar(keys(%unitsToReload)) > 0) {
print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n"; print STDERR "reloading the following units: ", join(", ", sort(keys(%unitsToReload))), "\n";
system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4; system("@systemd@/bin/systemctl", "reload", "--", sort(keys(%unitsToReload))) == 0 or $res = 4;
unlink($reloadListFile); unlink($reloadListFile);
} }
# Restart changed services (those that have to be restarted rather # Restart changed services (those that have to be restarted rather
# than stopped and started). # than stopped and started).
if (scalar(keys %unitsToRestart) > 0) { if (scalar(keys(%unitsToRestart)) > 0) {
print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"; print STDERR "restarting the following units: ", join(", ", sort(keys(%unitsToRestart))), "\n";
system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4; system("@systemd@/bin/systemctl", "restart", "--", sort(keys(%unitsToRestart))) == 0 or $res = 4;
unlink($restartListFile); unlink($restartListFile);
} }
@ -799,17 +800,17 @@ if (scalar(keys %unitsToRestart) > 0) {
# systemd. # systemd.
my @unitsToStartFiltered = filterUnits(\%unitsToStart); my @unitsToStartFiltered = filterUnits(\%unitsToStart);
print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n" print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n"
if scalar @unitsToStartFiltered; if scalar(@unitsToStartFiltered);
system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4; system("@systemd@/bin/systemctl", "start", "--", sort(keys(%unitsToStart))) == 0 or $res = 4;
unlink($startListFile); unlink($startListFile);
# Print failed and new units. # Print failed and new units.
my (@failed, @new); my (@failed, @new);
my $activeNew = getActiveUnits; my $activeNew = getActiveUnits();
while (my ($unit, $state) = each %{$activeNew}) { while (my ($unit, $state) = each(%{$activeNew})) {
if ($state->{state} eq "failed") { if ($state->{state} eq "failed") {
push @failed, $unit; push(@failed, $unit);
next; next;
} }
@ -819,7 +820,7 @@ while (my ($unit, $state) = each %{$activeNew}) {
chomp($main_status); chomp($main_status);
if ($main_status ne "0") { if ($main_status ne "0") {
push @failed, $unit; push(@failed, $unit);
next; next;
} }
} }
@ -827,19 +828,19 @@ while (my ($unit, $state) = each %{$activeNew}) {
# Ignore scopes since they are not managed by this script but rather # Ignore scopes since they are not managed by this script but rather
# created and managed by third-party services via the systemd dbus API. # created and managed by third-party services via the systemd dbus API.
# This only lists units that are not failed (including ones that are in auto-restart but have not failed previously) # This only lists units that are not failed (including ones that are in auto-restart but have not failed previously)
if ($state->{state} ne "failed" && !defined $activePrev->{$unit} && $unit !~ /\.scope$/msx) { if ($state->{state} ne "failed" && !defined($activePrev->{$unit}) && $unit !~ /\.scope$/msx) {
push @new, $unit; push(@new, $unit);
} }
} }
if (scalar @new > 0) { if (scalar(@new) > 0) {
print STDERR "the following new units were started: ", join(", ", sort(@new)), "\n" print STDERR "the following new units were started: ", join(", ", sort(@new)), "\n"
} }
if (scalar @failed > 0) { if (scalar(@failed) > 0) {
my @failed_sorted = sort @failed; my @failed_sorted = sort(@failed);
print STDERR "warning: the following units failed: ", join(", ", @failed_sorted), "\n\n"; print STDERR "warning: the following units failed: ", join(", ", @failed_sorted), "\n\n";
system "@systemd@/bin/systemctl status --no-pager --full '" . join("' '", @failed_sorted) . "' >&2"; system("@systemd@/bin/systemctl status --no-pager --full '" . join("' '", @failed_sorted) . "' >&2");
$res = 4; $res = 4;
} }
@ -849,4 +850,4 @@ if ($res == 0) {
syslog(LOG_ERR, "switching to system configuration $out failed (status $res)"); syslog(LOG_ERR, "switching to system configuration $out failed (status $res)");
} }
exit $res; exit($res);