我正在尝试构建一个 systemd 服务以在网络启动后运行。
/etc/systemd/system/caportal.service
[Unit]
Description=captive portal automation
DefaultDependencies=no
After=local-fs.target
[Service]
Type=oneshot
ExecStart=/sbin/wpa_cli -a /home/pi/test.sh -B
ExecStop=/usr/bin/pkill -f /home/pi/test.sh
RemainAfterExit=yes
[Install]
WantedBy=network.target
但此服务不会在重启时启动。只有通过 手动启动时才会启动sudo systemctl start caportal.service
。
但重启后,该服务的状态信息如下所示。
● 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.
如何在网络启动前在重启时启动服务?
答案1
否,状态输出表明你的脚本做过成功启动。但是,它运行也早期:日志显示wpa_cli有已启动,但因无法连接到 wpa_supplicant(现阶段尚未运行)而退出。
问题在于您试图在服务管理器视为一个单元的两个事件之间插入脚本:
- 您希望它在 wpa_supplicant 启动后运行(因为 wpa_cli 想要连接到它)。
- 您希望它在 wpa_supplicant 找到并关联网络之前运行。
仅靠 systemd 配置是无法实现这一点的。
您的一个选择是禁用自动连接,但添加一个执行开始帖子=脚本会告诉 wpa_supplicant 在 wpa_cli 成功启动后开始连接。或者,保留自动连接,但添加执行开始帖子=如果有必要,该脚本会手动触发 test.sh 操作。
您的设备存在的其他问题:
类型=oneshot告诉 systemd 认为这是一个运行后就退出的短暂单元,但
wpa_cli -a
显然不是这样——根据其手册页,它作为守护进程运行,并且需要类型=简单。退出后继续保留=是没有必要,因为这不是“一次性”服务。它只会引起混乱——例如,如果 wpa_cmd 崩溃,即使服务不再运行,它仍会显示为“活动”,因为此选项告诉它如此。
默认依赖项 = 否是不必要的;那是方式依赖顺序太早了。常规 wpa_supplicant 没有这个,所以这里也不需要;一个简单的之前=或者之后=通常就足够了。