У меня есть пользовательская служба в ~/.config/systemd/user/example.service
вот так:
[Unit]
Description=Example service
After=network.target
[Service]
ExecStart=/bin/bash -c 'host google.com > /var/tmp/example'
[Install]
WantedBy=default.target
Фактическая служба, которую я пытаюсь контролировать, на самом деле делает что-то полезное и, конечно же, получает доступ к сети; это просто упрощенный пример.
Услуга доступна через systemctl --user enable example.service
который создает символическую ссылку ~/.config/systemd/user/default.target.wants/example.service
указывает на ~/.config/systemd/user/example.service
.
С этой настройкой и с systemd
пользовательские сеансы включены, как описано на Arch Wiki, при запуске служба запускается от имени моего пользователя. Однако на самом деле он не запускается после настройки сети; вместо этого кажется, что он запускается немедленно, поскольку /var/tmp/example
содержит:
;; connection timed out; no servers could be reached
(И фактическая служба, которую я пытаюсь контролировать, также не может подключиться к сети и не работает с аналогичными ошибками поиска имени)
Это означает, что служба фактически не запускается после network.target
. Как мне заставить его ждать network.target
перед запуском?
У меня была такая же проблема со сценарием резервного копирования пользовательского пространства, которому нужен доступ к Интернету. Я решил это, добавив ~/.config/systemd/user/wait-for-network.service
это просто пинг google.com
пока он не станет доступным:
[Unit]
Description=Ping a server on the internet until it becomes reachable
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'while ! ping -c1 google.com; do sleep 1; done'
TimeoutStartSec=60s
Затем я сделал свой сценарий резервного копирования зависимым от него следующим образом:
[Unit]
Description=...
Requires=wait-for-network.service
After=wait-for-network.service
Это работает независимо от того, используете ли вы NetworkManager
или каким-либо другим способом установить соединение.
Забудь network.target
. man systemd.special
говорит:
network.target systemd automatically adds dependencies of type After for this target unit to all SysV init script service units with an LSB header referring to the $network facility.
Таким образом, эта цель в первую очередь является хаком для совместимости скриптов инициализации SysV.
Предполагая, что ваше сетевое соединение обрабатывается NetworkManager, вы, конечно, были правы, полагаясь на эту цель, потому что NetworkManager.service
определяет Before=network.target
. Но это означает только то, что NetworkManager запущен, а не то, что сетевое соединение фактически установлено. Это может занять некоторое время (обходы по протоколу DHCP, рукопожатие Wi-Fi и т. Д.) И полностью является делом NetworkManager. По крайней мере, в моей системе (F18) есть служба под названием NetworkManager-wait-online
. Он использует nm-online
служебная программа для блокировки до тех пор, пока не будет установлено активное соединение. Пробовать Require, Before
это в определении вашего модуля или используйте этот инструмент отдельно.