Systemd ExecCondition failing unexpectedly

I’ve set

  systemd.user = {
...
    services."daily" = {
...
      serviceConfig = {
        Type = "oneshot";
      # ExecCondition = "${pkgs.networkmanager}/bin/nm-online -q && ${pkgs.iputils}/bin/ping -qc 1 -w 30 -i 0.1 github.com";
        ExecCondition = "${pkgs.networkmanager}/bin/nm-online -q; ${pkgs.iputils}/bin/ping -qc 1 -w 30 -i 0.1 github.com";
      };
...

which gives me

$ systemctl -ln 9999 --user status daily                                                                                                                                             
○ daily.service
     Loaded: loaded (/etc/systemd/user/daily.service; static)
     Active: inactive (dead) (Result: exec-condition) since Tue 2024-04-23 07:00:22 CEST; 2min 28s ago
TriggeredBy: ● daily.timer
  Condition: start condition unmet at Tue 2024-04-23 07:00:22 CEST; 2min 28s ago
    Process: 3942 ExecCondition=/nix/store/29na1ngnjg8vmf3471yay647c633jkfp-networkmanager-1.46.0/bin/nm-online -q; /nix/store/bjpk11pia9dzblfzi0qg31yh919id83w-iputils-20240117/bin/ping -qc 1 -w 30 -i 0.1 github.com (code=exited, status=2)
        CPU: 7ms

Apr 23 07:00:22 nixos systemd[1628]: Starting daily.service...
Apr 23 07:00:22 nixos nm-online[3942]: /nix/store/29na1ngnjg8vmf3471yay647c633jkfp-networkmanager-1.46.0/bin/nm-online: Invalid option.  Please use --help to see a list of valid options.
Apr 23 07:00:22 nixos systemd[1628]: daily.service: Skipped due to 'exec-condition'.
Apr 23 07:00:22 nixos systemd[1628]: Condition check resulted in daily.service being skipped.
Apr 23 07:00:22 nixos systemd[1628]: daily.service: Triggering OnSuccess= dependencies.

I tried both variants of the ExecCondition (the one with && and with ;) to make sure that this isn’t caused by systemd using the user shell (nushell) and not /bin/sh (bash) but it fails in both cases. ExecCondition = ''bash -c "${pkgs.networkmanager}/bin/nm-online -q && ${pkgs.iputils}/bin/ping -qc 1 -w 30 -i 0.1 github.com"''; doesn’t work as well so this doesn’t seem to be the reason.

I don’t understand why the condition fails. It succeeds when i run nm-online -q; ping -qc 1 -w 30 -i 0.1 github.com from the terminal and i use it as a condition in my window manager for the autostart of programs (the browser is launched only after this condition is satisfied) which works as well.

Why is the condition failing in systemd? Am i not allowed to chain commands like this?

It’s not using a shell at all. Check the COMMAND LINES section in systemd.service(5). It isn’t parsing commands like a shell would. It does allow using a semicolon to put multiple commands in the same directive, but the semicolon has to be its own word. i.e. You need a space before your semicolon. Actually, I would just specify the directive multiple times; once for each command. You can do this in the nix config by setting serviceConfig.ExecCondition to a nix list of commands.

2 Likes

Oh i see, thank you for your help!

To be sure that i understood it correctly:

I’ve now set ExecCondition = ["${pkgs.networkmanager}/bin/nm-online -q" "${pkgs.iputils}/bin/ping -qc 1 -w 30 -i 0.1 github.com"];.

Will this execute the first command and wait until it succeeds before executing the second command (like && in bash) or will they be run at the same time? I need to have them run one after the other, because ping will fail immediately if there is no network up.

They’ll be run one at a time.

1 Like