Skip to content
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

Merged
merged 1 commit into from Aug 27, 2018

Conversation

Ma27
Copy link
Member

@Ma27 Ma27 commented Aug 13, 2018

Motivation for this change

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.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Fits CONTRIBUTING.md.

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'");
Copy link
Member

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.

Copy link
Member Author

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;
Copy link
Member

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?

Copy link
Member Author

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!

@Ma27 Ma27 force-pushed the reload-user-units-during-activation branch from 85bf866 to 8e7b141 Compare August 13, 2018 22:51
@Ma27
Copy link
Member Author

Ma27 commented Aug 13, 2018

@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';
Copy link
Member

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.

@Ma27 Ma27 force-pushed the reload-user-units-during-activation branch from 8e7b141 to 96d6cc0 Compare August 14, 2018 09:30
@Ma27
Copy link
Member Author

Ma27 commented Aug 14, 2018

@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';
Copy link
Member

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;
Copy link
Member

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");
Copy link
Member

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.

Copy link
Member Author

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.
@Ma27 Ma27 force-pushed the reload-user-units-during-activation branch from 96d6cc0 to fc2bde6 Compare August 14, 2018 11:38
@Ma27
Copy link
Member Author

Ma27 commented Aug 14, 2018

@Mic92 done!

@Ma27
Copy link
Member Author

Ma27 commented Aug 27, 2018

@edolstra @Mic92 any chance to get this merged before the 18.09 branchoff? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants