¿Cómo puedo hacer que mis servicios de usuario esperen hasta que la red esté en línea?

14

He escrito un par de archivos de servicio de usuario systemd que quiero que los usuarios habiliten y que necesiten una conexión de red que funcione. Pensé que sería tan fácil como:

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

Sin embargo, los servicios parecen comenzar demasiado temprano, y journalctlveo:

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

Luego busqué más y probé

Wants=network.target
After=network.target

y lo hizo sudo systemctl enable systemd-networkd-wait-online.service.

Ahora tengo en journalctl:

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

Y nuevamente el servicio comienza demasiado temprano.

¿Se supone que ese mensaje debe estar allí? ¿Cómo puedo depurar mi problema?


EDITAR : la razón es simple y está específicamente establecida en Arch Wiki :

systemd --userse ejecuta como un proceso separado del systemd --systemproceso. Las unidades de usuario no pueden hacer referencia o depender de las unidades del sistema.

Esta publicación en el foro parece sugerir una solución simple: debería linkusar la unidad del sistema necesaria como usuario, creando así un enlace simbólico disponible en la ruta de búsqueda de la unidad.

Después de hacer eso, no veo ningún No such file or directorymensaje, sin embargo, todavía no puedo hacer que los servicios realmente se ejecuten después de que la red esté en línea. He tratado de unión network.target, network-online.targety systemd-networkd-wait-online.service, fijando mis unidades a depender de cada uno de ellos, sin éxito. Cuando verifico el estado de la unidad vinculada en modo de usuario, todos están muertos, por ejemplo:

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

Sin embargo, puedo ver network-online.targetactivo en modo de usuario después de vincularlo:

$ 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
fuente
Espero que tengas una respuesta.
@Deleteme Gracias, creo que encontré la causa de esto (ver actualización), pero no cómo resolver el problema.
Lev Levitsky
¿Alguna vez encontraste una solución a este problema? Además, noto que enfatiza que solo algunas unidades vinculadas están muertas. ¿Cuáles son los que funcionaron y en qué se diferencian?
Sparhawk
@Sparhawk lamentablemente no. Como solución alternativa, solo uso temporizadores establecidos en varios segundos después del arranque. La pregunta tiene un ejemplo: el objetivo de red en línea está activo después de la vinculación, y el objetivo de red no lo está.
Lev Levitsky
Tal vez no entiendo bien, pero estoy buscando algo para disparar cada vez que se reanuda la red, para revisar mi correo electrónico después de reanudar la suspensión. Pensé que esta sería la forma de hacerlo. Ahora veo los ejemplos. Pensé que querías decir que algunos servicios personalizados se dispararon y otros no. Sin embargo, ahora veo que está hablando de las versiones de usuario de los objetivos de red.
Sparhawk

Respuestas:

3

Como no puede depender de un servicio del sistema, su única solución es proporcionar un servicio de usuario que detecte si la red está en línea. (O haga que sus servicios sean servicios del sistema). Los detalles para un servicio de usuario "detectar en línea" dependerán de su definición de "en línea". Podría esperar un ping a 8.8.8.8 para tener éxito, por ejemplo. O para que una resolución de nombre DNS tenga éxito. Por ejemplo, en una situación similar con vpnc, espero que un ping a una IP vpn tenga éxito.

Luego, puede hacer que sus servicios de usuario dependan de (After =) su servicio de detección en línea.

#!/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
fuente
Gracias, esto parece razonable y lo suficientemente simple. Pero si 10 usuarios habilitan mi servicio de usuario, habrá 10 instancias haciendo ping al mismo servidor simultáneamente, lo que parece un poco redundante. En la práctica, esto probablemente no sea un problema, pero estaba preguntando esto con la esperanza de obtener una única "bandera en línea" disponible para todos los servicios de usuario. Sin embargo, aún no se han sugerido mejores soluciones.
Lev Levitsky
1

Yo recomendaría probar algo como esto:

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

Seguido por:

# systemctl daemon-reload && systemctl enable foo.service
Marius Karnauskas
fuente
44
Pero este es un servicio del sistema, y ​​estoy tratando de configurar un servicio de usuario.
Lev Levitsky