Comment faire attendre mes services utilisateurs jusqu'à ce que le réseau soit en ligne?

14

J'ai écrit quelques fichiers de service utilisateur systemd que je souhaite que les utilisateurs activent et qui nécessitent une connexion réseau fonctionnelle. J'ai pensé que ce serait aussi simple que:

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

Cependant, les services semblent commencer trop tôt, et journalctlje vois:

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

Ensuite, j'ai cherché plus et essayé

Wants=network.target
After=network.target

et l'a fait sudo systemctl enable systemd-networkd-wait-online.service.

Maintenant, j'ai journalctl:

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

Et encore une fois, le service commence trop tôt.

Ce message est-il censé être là? Comment puis-je déboguer mon problème?


EDIT : la raison est simple et spécifiquement indiquée dans l' Arch Wiki :

systemd --users'exécute en tant que processus distinct du systemd --systemprocessus. Les unités utilisateur ne peuvent pas référencer ou dépendre des unités système.

Ce message de forum semble suggérer une solution simple: je devrais linkl'unité système nécessaire en tant qu'utilisateur, créant ainsi un lien symbolique vers celui-ci disponible sur le chemin de recherche de l'unité.

Après cela, je ne vois aucun No such file or directorymessage, cependant, je ne peux toujours pas faire fonctionner les services une fois le réseau en ligne. J'ai essayé liaison network.target, network-online.targetet systemd-networkd-wait-online.service, la mise en mes unités à dépendre de chacun d'eux, sans succès. Lorsque je vérifie l'état de l'unité liée en mode utilisateur, ils sont tous certains morts, par exemple:

$ 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.

Cependant, je peux voir network-online.targetactif en mode utilisateur après l'avoir lié:

$ 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.
Lev Levitsky
la source
J'espère que vous aurez une réponse.
@Deleteme Merci, je pense avoir trouvé la cause de cela (voir la mise à jour), mais pas comment résoudre le problème.
Lev Levitsky
Avez-vous tous trouvé une solution à ce problème? De plus, je remarque que vous insistez sur le fait que seules certaines unités liées sont mortes. Quels sont ceux qui ont fonctionné et en quoi diffèrent-ils?
Sparhawk
@Sparhawk malheureusement pas. Pour contourner ce problème, j'utilise simplement des minuteries définies sur plusieurs secondes après le démarrage. La question a un exemple: la cible réseau en ligne est active après la liaison et la cible réseau ne l'est pas.
Lev Levitsky
Peut-être que je me méprends, mais je cherche quelque chose à déclencher chaque fois que le réseau reprend, pour vérifier mes e-mails après la reprise de la suspension. Je pensais que ce serait la façon de procéder. Je vois les exemples maintenant. Je pensais que vous vouliez dire que certains services personnalisés avaient été licenciés et d'autres non. Cependant, je vois maintenant que vous parlez des versions utilisateur des cibles réseau.
Sparhawk

Réponses:

3

Comme vous ne pouvez pas dépendre d'un service système, votre seule solution est de fournir un service utilisateur qui détecte si le réseau est en ligne. (Ou faites en sorte que votre système de services devienne un service.) Les détails d'un service utilisateur "détecter en ligne" dépendraient de votre définition de "en ligne". Il pourrait par exemple attendre qu'un ping vers 8.8.8.8 réussisse. Ou pour qu'une résolution de nom DNS réussisse. Par exemple, dans une situation similaire avec vpnc, j'attends qu'un ping vers une IP vpn réussisse.

Ensuite, vous pouvez faire dépendre vos services utilisateurs de (After =) votre service utilisateur de détection en ligne.

#!/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
Stuart Gathman
la source
Merci, cela semble raisonnable et assez simple. Mais si 10 utilisateurs activent mon service utilisateur, il y aura 10 instances de ping sur le même serveur simultanément, ce qui semble un peu redondant. En pratique, ce n'est probablement pas un problème, mais je le demandais dans l'espoir de mettre un "drapeau en ligne" à la disposition de tous les services utilisateurs. Cependant, aucune meilleure solution n'a encore été suggérée.
Lev Levitsky
1

Je recommanderais de tester quelque chose comme ceci:

# /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

Suivi par:

# systemctl daemon-reload && systemctl enable foo.service
Marius Karnauskas
la source
4
Mais il s'agit d'un service système et j'essaie de mettre en place un service utilisateur.
Lev Levitsky