New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nixos/switch-to-configuration: reload user units #44990
Conversation
my $name = getpwuid(int($f)); | ||
print STDERR "reloading user units for $name...\n"; | ||
|
||
system("su -l $name -c \$'XDG_RUNTIME_DIR=/run/user/$f @systemd@/bin/systemctl --user daemon-reload'"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running programs under arbitrary user accounts from a root script frightens me. In any case, it should be
system("su", "-l", $name, "-c" "command...");
to prevent shell interpolation etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx, totally missed that!
@@ -412,6 +412,21 @@ sub filterUnits { | |||
# Make systemd reload its units. | |||
system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3; | |||
|
|||
# Reload user units | |||
opendir (DIR, "/run/user") or $res = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this use loginctl
to get active sessions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look into this. I thought of reading /run/user
first as easiest approach to get active sessions, but if there's an easier way to implement this in perl with loginctl
I'll change this!
85bf866
to
8e7b141
Compare
@edolstra would you mind having another look at this? I switched to a loginctl-based approach now, but I'm not a Perl expert, so I'm not sure if there's still a better solution 😅 |
@@ -412,6 +412,19 @@ sub filterUnits { | |||
# Make systemd reload its units. | |||
system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3; | |||
|
|||
# Reload user units | |||
open my $listActiveUsers, '-|', '@systemd@/bin/loginctl list-users | @coreutils@/bin/tail -n +2 | @coreutils@/bin/head -n -2'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
=> loginctl list-users --no-legend
.
8e7b141
to
96d6cc0
Compare
@edolstra done! |
@@ -412,6 +412,19 @@ sub filterUnits { | |||
# Make systemd reload its units. | |||
system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3; | |||
|
|||
# Reload user units | |||
open my $listActiveUsers, '-|', '@systemd@/bin/loginctl list-users --no-legend'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not make a difference here, but for consistency splitting arguments is better.
open my $listActiveUsers, '-|', '@systemd@/bin/loginctl', 'list-users', '--no-legend';
while (my $f = <$listActiveUsers>) { | ||
$f =~ s/^\s+//; | ||
$f =~ s/\s+\n$//; | ||
my ($uid, $name) = split / /, $f, 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use a single regex instead of three.
next unless $f =~ /^\s*(?<uid>\d+)\s+(?<user>\S+)/;
my ($uid, $name) = ($+{uid}, $+{user});
This code also skips if it does not match.
my ($uid, $name) = split / /, $f, 2; | ||
print STDERR "reloading user units for $name...\n"; | ||
|
||
system("su", "-l", $name, "-c", "XDG_RUNTIME_DIR=/run/user/$uid @systemd@/bin/systemctl --user daemon-reload"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can daemon-reload start services? If so it might be better of after systemd-tmpfiles
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it simply reloads the configuration files in /etc/systemd/user
, you have to restart them manually ATM. Some lines above the same will be done for system-wide services.
The patch simply reloads the services, but doesn't restart them. I started working on this locally, but this task is way harder and will take some time before I can file a usable patch. However I thought that this change might be worth to publish for now :)
When rebuilding you have to manually run `systemctl --user daemon-reload`. It gathers all authenticated users using `loginctl list-user` and runs `daemon-reload` for each of them. This is a first step towards a `nixos-rebuild` which is able to reload user units from systemd. The entire task is fairly hard, however I consider this patch usable as it allows to restart units without running `daemon-reload` for each authenticated user.
96d6cc0
to
fc2bde6
Compare
@Mic92 done! |
Motivation for this change
When rebuilding you have to manually run
systemctl --user daemon-reload
. It gathers all authenticated users usingloginctl list-user
and runsdaemon-reload
for each of them.This is a first step towards a
nixos-rebuild
which is able to reloaduser units from systemd. The entire task is fairly hard, however I
consider this patch usable as it allows to restart units without running
daemon-reload
for each authenticated user.Things done
sandbox
innix.conf
on non-NixOS)nix-shell -p nox --run "nox-review wip"
./result/bin/
)nix path-info -S
before and after)