8

I wrote a systemd service to launch a wireless access point whenever the machine boots. My problem is that it is not actually started when the machine boots, and I cannot seem to find out why. Starting the service manually works fine.

My wap.service systemd unit file:

[Unit]
Description=Enable the Wireless Access Point
Requires=dnsmasq.service iptables.service NetworkManager.service
Before=dnsmasq.service
After=iptables.service NetworkManager.service

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/project/wap.sh
TimeoutStartSec=0

[Install]
WantedBy=default.target

/project/wap.sh (the curly brackets are Ansible/Jinja2 variable substitution):

#!/usr/bin/env bash

set -Eeuo pipefail

# Allow incoming DNS requests.
iptables -I INPUT -p udp --dport 53 -j ACCEPT -m comment --comment "DNS"

# Allow incoming DHCP requests.
iptables -I INPUT -p udp --dport 67 -j ACCEPT -m comment --comment "DHCP"

# Relinquish NetworkManager control over the wireless network interface.
nmcli r wifi off
rfkill unblock wifi

# Up and configure the wireless network interface.
ifconfig {{ap_interface}} 192.168.2.1 up
route add -net 0.0.0.0 netmask 255.255.255.0 gw 192.168.2.1 || true

# Restart hostapd so it can successfully bind to the newly configured wireless network interface.
service hostapd restart

The relevant /usr/lib/systemd/systemd --test --system --unit=default.target output:

    -> Unit wap.service:
        Description: Enable the Wireless Access Point
        Instance: n/a
        Unit Load State: loaded
        Unit Active State: inactive
        Inactive Exit Timestamp: n/a
        Active Enter Timestamp: n/a
        Active Exit Timestamp: n/a
        Inactive Enter Timestamp: n/a
        GC Check Good: no
        Need Daemon Reload: no
        Transient: no
        Slice: system.slice
        CGroup: n/a
        CGroup realized: no
        CGroup mask: 0x0
        CGroup members mask: 0x0
        Name: wap.service
        Fragment Path: /etc/systemd/system/wap.service
        Requires: dnsmasq.service
        Requires: NetworkManager.service
        Requires: basic.target
        Requires: iptables.service
        Wants: system.slice
        WantedBy: multi-user.target
        Conflicts: shutdown.target
        Before: dnsmasq.service
        Before: multi-user.target
        Before: shutdown.target
        After: systemd-journald.socket
        After: iptables.service
        After: NetworkManager.service
        After: system.slice
        After: basic.target
        References: systemd-journald.socket
        References: iptables.service
        References: NetworkManager.service
        References: system.slice
        References: dnsmasq.service
        References: shutdown.target
        References: basic.target
        ReferencedBy: multi-user.target
        StopWhenUnneeded: no
        RefuseManualStart: no
        RefuseManualStop: no
        DefaultDependencies: yes
        OnFailureJobMode: replace
        IgnoreOnIsolate: no
        IgnoreOnSnapshot: no
        Service State: dead
        Result: success
        Reload Result: success
        PermissionsStartOnly: no
        RootDirectoryStartOnly: no
        RemainAfterExit: yes
        GuessMainPID: yes
        Type: oneshot
        Restart: no
        NotifyAccess: none
        NotifyState: unknown
        KillMode: control-group
        KillSignal: SIGTERM
        SendSIGKILL: yes
        SendSIGHUP:  no
        UMask: 0022
        WorkingDirectory: /
        RootDirectory: /
        NonBlocking: no
        PrivateTmp: no
        PrivateNetwork: no
        PrivateDevices: no
Loaded units and determined initial transaction in 75ms.        ProtectHome: no
        ProtectSystem: no

        IgnoreSIGPIPE: yes
        LimitNOFILE: 1024 4096
        StandardInput: null
        StandardOutput: journal
        StandardError: inherit
        SyslogFacility: daemon
        SyslogLevel: info
        -> ExecStart:
            Command Line: /project/wap.sh

The service status after a reboot:

$ sudo service wap status -l
Redirecting to /bin/systemctl status  -l wap.service
● wap.service - Enable the Wireless Access Point
   Loaded: loaded (/etc/systemd/system/wap.service; enabled; vendor preset: disabled)
   Active: inactive (dead)

The service status after starting it manually:

$ sudo service wap start
Redirecting to /bin/systemctl start wap.service
$ sudo service wap status -l
Redirecting to /bin/systemctl status  -l wap.service
● wap.service - Enable the Wireless Access Point
   Loaded: loaded (/etc/systemd/system/wap.service; enabled; vendor preset: disabled)
   Active: active (exited) since do 2019-09-26 12:10:40 BST; 6s ago
  Process: 8589 ExecStart=/project/wap.sh (code=exited, status=0/SUCCESS)
 Main PID: 8589 (code=exited, status=0/SUCCESS)

sep 26 12:10:40 localhost.localdomain systemd[1]: Starting Enable the Wireless Access Point...
sep 26 12:10:40 localhost.localdomain wap.sh[8589]: Redirecting to /bin/systemctl restart hostapd.service
sep 26 12:10:40 localhost.localdomain systemd[1]: Started Enable the Wireless Access Point.

journalctl output:

$ journalctl -u wap
-- No entries --

I have confirmed wap.sh is never run when the machine boots, but I have not been able to find anything about this service in the syslog, such as attempts to start the service.

TLDR; My service should start on boot, but doesn't, and I don't understand why.

2
  • You are correct; sorry for the typo -- must have been an auto-"correct" that I didn't catch. Would you please edit the journalctl -u wap, which gives -- No entries -- portion into your question? Thank you!
    – Jeff Schaller
    Commented Oct 4, 2019 at 14:11
  • Done. Thanks for the reminder!
    – Xano
    Commented Oct 4, 2019 at 14:26

4 Answers 4

8

Maybe as easy as?:

systemctl enable wap.service

2
  • The sudo service wap status -l shown in the opening post shows the service is enabled (I use Ansible for that). I explicitly enabled the service again using systemctl but no apparent changes were made, and the service still does not start after a reboot.
    – Xano
    Commented Oct 4, 2019 at 13:59
  • 1
    Whoops, sorry I missed that. You say wap.sh is never run on machine reboot -- how have you confirmed this? Is /project/wap.sh on a separate fs that might not be mounted yet when your service runs at boot time? Otherwise I'd suspect that your service depends on some other part of your system that's available after fully booted, but not when your service runs at boot time. The trick is to figure out which part(s), and to explicitly declare them in your service so that it waits until they're available before running. Sorry I don't have specific suggestions.
    – fmyhr
    Commented Oct 5, 2019 at 14:55
3

The cause of my problem turned out to be a non-existent target. Instead of default.target (which is a symlink, at least on CentOS, but does not correspond to a runlevel), I should have used multi-user.target, which corresponds to runlevel 3. The correct configuration then becomes:

[Install]
WantedBy=multi-user.target

Thank you, everyone, for your time and feedback!

0

Systemd service files only get read and their ordering and dependency linked into the graphs if they are enabled, usually by having symlinks in one of the want directories for their target or service (usually in /etc/systemd/system/ for user-created services). A systemctl enable operation will instantiate these links from those listed in the [Install] section of the service file.

0

After fixing the system unit I had to disable and re-enable the service

# systemctl disable etcd
Removed /etc/systemd/system/multi_user.target.wants/etcd.service.


# systemctl enable etcd
Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /etc/systemd/system/etcd.service.
## note the path changed 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .