I was trying to build a systemd service to run after the networking is up.


Description=captive portal automation



ExecStart=/sbin/wpa_cli -a /home/pi/test.sh -B
ExecStop=/usr/bin/pkill -f /home/pi/test.sh



But this service does not start at reboot. It start when manually started by sudo systemctl start caportal.service.

But after reboot, the status information of this service was given below.

● caportal.service - captive portal automation
   Loaded: loaded (/etc/systemd/system/caportal.service; enabled)
   Active: failed (Result: exit-code) since Thu 2019-04-11 10:59:32 UTC; 3min 3s ago
  Process: 287 ExecStart=/sbin/wpa_cli -a /home/pi/test.sh -B (code=exited, status=255)
 Main PID: 287 (code=exited, status=255)

Apr 11 10:59:32 raspberrypi systemd[1]: Starting captive portal automation...
Apr 11 10:59:32 raspberrypi wpa_cli[287]: Failed to connect to non-global ctrl_ifname: (null)  error: No such file or directory
Apr 11 10:59:32 raspberrypi systemd[1]: caportal.service: main process exited, code=exited, status=255/n/a
Apr 11 10:59:32 raspberrypi systemd[1]: Failed to start captive portal automation.
Apr 11 10:59:32 raspberrypi systemd[1]: Unit caportal.service entered failed state.

How to start the service at reboot before the network start?


No, the status output says that your script did start successfully. However, it ran too early: the log shows that wpa_cli had been started, but exited because it couldn't connect to wpa_supplicant – which at this stage is not running yet.

The problem is that you're trying to insert the script between two events which the service manager considers as a single unit:

  1. You want it to run after wpa_supplicant has started (because wpa_cli wants to connect to it).
  2. You want it to run before wpa_supplicant has found and associated with a network.

There's no way you can achieve this with systemd configuration alone.

One of your options is to disable automatic connection but add an ExecStartPost= script which tells wpa_supplicant to begin connecting after wpa_cli has successfully started. Alternatively, keep automatic connection, but add an ExecStartPost= script which manually triggers the test.sh actions if necessary.

Further problems with your unit:

  • Type=oneshot tells systemd to expect that this is a short-lived unit that runs and exits, but wpa_cli -a obviously isn't that – according to its manual page, it runs as a daemon and needs Type=simple.

  • RemainAfterExit=yes is unnecessary because this isn't an 'oneshot' service. It'll only cause confusion – e.g. if wpa_cmd crashes, the service would still appear "active" even though it isn't running anymore, because this option told it so.

  • DefaultDependencies=no is unnecessary; that's way too early in terms of dependency ordering. Regular wpa_supplicant doesn't have this, so it's not needed here either; a simple Before= or After= is usually enough.

  • Thanks @grawity. Can I start the script after wpa_supplicant.service? Also How to view the order in which systemd process each service? – mcv Apr 12 '19 at 4:00
  • Sure, [Unit] After=wpa_supplicant.service. But you can't guarantee that it'll run before or after wpa_supplicant has done something-or-other, only that it'll run after it has "started". Use systemctl list-dependencies --after, --before, and maybe systemd-analyze dot | dot -Tx11? – user1686 Apr 12 '19 at 4:20
  • yeah, I have already tried that After=wpa_supplicant.service. But it wasn't working. Now it shows the service as inactive – mcv Apr 12 '19 at 4:57
  • systemctl list-dependencies --after, this list not showing wpa_supplicant.service` – mcv Apr 12 '19 at 4:58
  • Did you tell it to list caportal.service? – user1686 Apr 12 '19 at 4:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.