Как я могу заставить свои пользовательские сервисы ждать, пока сеть не станет онлайн?

14

Я написал пару системных файлов пользовательских служб, которые я хочу, чтобы пользователи включали, и которым требуется работающее сетевое соединение. Я думал, что это будет так же просто, как:

Wants=network-online.target
After=network-online.target

Тем не менее, службы, кажется, начинают слишком рано, и journalctlя вижу:

network-online.target: Cannot add dependency job, ignoring: Unit network-online.target failed to load: No such file or directory.

Тогда я искал больше и пытался

Wants=network.target
After=network.target

и сделал sudo systemctl enable systemd-networkd-wait-online.service.

Теперь я имею в journalctl:

network.target: Cannot add dependency job, ignoring: Unit network.target failed to load: No such file or directory.

И снова сервис запускается слишком рано.

Это сообщение должно быть там? Как я могу отладить мою проблему?


РЕДАКТИРОВАТЬ : причина проста и конкретно изложена в Arch Wiki :

systemd --userработает как отдельный процесс от systemd --systemпроцесса. Пользовательские блоки не могут ссылаться или зависеть от системных блоков.

Этот пост на форуме, кажется, предлагает простое решение: я должен linkиспользовать необходимый системный блок как пользователь, создавая тем самым символическую ссылку на него, доступную в пути поиска модулей.

После этого я не вижу никаких No such file or directoryсообщений, однако я все еще не могу заставить службы фактически работать после того, как сеть подключена. Я попытался связывание network.target, network-online.targetи systemd-networkd-wait-online.service, установив свои единицы, зависит от каждого из них, но безуспешно. Когда я проверяю состояние связанного устройства в пользовательском режиме, все они некоторые из них мертвы, например:

$ systemctl --user status network.target
● network.target - Network
   Loaded: loaded (/usr/lib/systemd/system/network.target; linked; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:systemd.special(7)
           http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
$ systemctl status network.target
● network.target - Network
   Loaded: loaded (/usr/lib/systemd/system/network.target; static; vendor preset: disabled)
   Active: active since Sat 2015-07-18 19:20:11 MSK; 3h 35min ago
     Docs: man:systemd.special(7)
           http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget

Jul 18 19:20:11 calc-server systemd[1]: Reached target Network.
Jul 18 19:20:11 calc-server systemd[1]: Starting Network.

Тем не менее, я вижу network-online.targetактивным в пользовательском режиме после его ссылки:

$ systemctl --user status network-online.target
● network-online.target - Network is Online
   Loaded: loaded (/usr/lib/systemd/system/network-online.target; linked; vendor preset: enabled)
   Active: active since Sun 2015-07-19 00:35:38 MSK; 2min 48s ago
     Docs: man:systemd.special(7)
           http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget

Jul 19 00:35:38 calc-server systemd[469]: Reached target Network is Online.
Jul 19 00:35:38 calc-server systemd[469]: Starting Network is Online.
Лев Левицкий
источник
Я надеюсь, что у вас будет ответ.
@Deleteme Спасибо, я думаю, что нашел причину этого (см. Обновление), но не как решить проблему.
Лев Левицкий,
Вы когда-нибудь находили решение этой проблемы? Кроме того, я замечаю, что вы подчеркиваете, что только некоторые связанные единицы мертвы Какие из них работали, и чем они отличаются?
Sparhawk
@ Sparhawk, к сожалению, нет. В качестве обходного пути я просто использую таймеры, установленные на несколько секунд после загрузки. У вопроса есть пример: цель сетевого подключения активна после связывания, а цель сети - нет.
Лев Левицкий
Возможно, я неправильно понимаю, но я ищу что-то, что срабатывает при каждом возобновлении работы сети, чтобы проверить свою электронную почту после возобновления из режима ожидания. Я думал, что это будет способ сделать это. Теперь я вижу примеры. Я думал, что вы имели в виду некоторые таможенные службы уволены, а некоторые нет. Однако теперь я вижу, что вы говорите о пользовательских версиях сетевых целей.
Sparhawk

Ответы:

3

Поскольку вы не можете зависеть от системной службы, единственным решением для вас является предоставление пользовательской службы, которая определяет, подключена ли сеть. (Или сделайте ваши услуги системными службами.) Подробная информация о службе обнаружения «онлайн» будет зависеть от вашего определения «онлайн». Например, он может ждать пинга до 8.8.8.8. Или для разрешения имен DNS для успеха. Например, в аналогичной ситуации с vpnc я ожидаю, пока ping к IP-адресу vpn завершится успешно.

Затем вы можете сделать так, чтобы ваши пользовательские сервисы зависели от (после =) вашего пользовательского сервиса обнаружения в Интернете.

#!/bin/sh

host="${1:-8.8.8.8}"

pingcheck() {
  ping -n -c 1 -w 5 $1 >/dev/null 2>&1
}

# Do you want a timeout ?
while :; do
  pingcheck ${host} && exit 0
  sleep 10
done
Стюарт Гатман
источник
Спасибо, это кажется разумным и достаточно простым. Но если 10 пользователей активируют мой пользовательский сервис, будет 10 экземпляров, которые будут пинговать один и тот же сервер одновременно, что кажется немного избыточным. На практике это, вероятно, не является проблемой, но я спрашивал об этом в надежде получить единый «онлайн-флаг», доступный для всех пользовательских служб. Однако лучшие решения пока не предложены.
Лев Левицкий
1

Я бы порекомендовал проверить что-то вроде этого:

# /etc/systemd/system/foo.service
[Unit]
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/logger -t foo "testing online target"

[Install]
WantedBy=multi-user.target

С последующим:

# systemctl daemon-reload && systemctl enable foo.service
Мариус Карнаускас
источник
4
Но это системный сервис, и я пытаюсь настроить пользовательский сервис.
Лев Левицкий