Como posso fazer com que meus serviços ao usuário esperem até que a rede esteja on-line?

12

Escrevi alguns arquivos de serviço do usuário systemd que desejo que os usuários ativem e que precisem de uma conexão de rede ativa. Eu pensei que seria tão fácil quanto:

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

No entanto, os serviços parecem começar muito cedo e, em journalctl , vejo:

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

Então eu procurei mais e tentei

Wants=network.target
After=network.target

e fez sudo systemctl enable systemd-networkd-wait-online.service .

Agora eu tenho em journalctl :

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

E mais uma vez o serviço começa cedo demais.

Essa mensagem deveria estar lá? Como posso depurar meu problema?

EDITAR : o motivo é simples e especificamente declarado no Arch Wiki :

systemd --user runs as a separate process from the systemd --system process. User units can not reference or depend on system units.

Esta postagem no fórum parece sugerir uma solução simples: eu deveria link o necessário unidade de sistema como um usuário, criando assim um link simbólico para ele disponível no caminho de pesquisa da unidade.

Depois de fazer isso, não vejo nenhuma mensagem No such file or directory , no entanto, ainda não consigo fazer os serviços realmente serem executados depois que a rede estiver on-line. Eu tentei vincular network.target , network-online.target e systemd-networkd-wait-online.service , definindo minhas unidades para depender de cada uma delas, sem sucesso. Quando verifico o status da unidade vinculada no modo de usuário, eles são todos , alguns deles estão mortos, por exemplo:

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

No entanto, posso ver network-online.target ativo no modo de usuário depois de vinculá-lo:

$ 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.
    
por Lev Levitsky 18.07.2015 / 15:10

2 respostas

4

Como você não pode depender de um serviço do sistema, sua única solução é fornecer um serviço do usuário que detecte se a rede está on-line. (Ou faça os serviços do sistema de serviços.) Os detalhes de um serviço de usuário "detect-online" dependerão da sua definição de "online". Ele poderia esperar por um ping para 8.8.8.8 ter sucesso, por exemplo. Ou para uma resolução de nomes DNS ter sucesso. Por exemplo, em uma situação parecida com o vpnc, eu espero que um ping para um IP vpn tenha sucesso.

Em seguida, você pode fazer com que seus serviços de usuário dependam de (Após =) seu serviço de usuário on-line de detecção.

#!/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
    
por 16.12.2015 / 01:10
1

Eu recomendaria testar algo assim:

# /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
    
por 03.12.2015 / 04:23