Como posso fazer com que meus serviços de usuário esperem até a rede estar online?

14

Escrevi alguns arquivos de serviço do usuário systemd que eu quero que os usuários ativem e que precisam de uma conexão de rede em funcionamento. 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 journalctlvejo:

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, novamente, o serviço começa muito cedo.

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


EDIT : o motivo é simples e especificamente indicado no Arch Wiki :

systemd --useré executado como um processo separado do systemd --systemprocesso. As unidades do usuário não podem fazer referência ou depender das unidades do sistema.

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

Depois disso, não vejo nenhuma No such file or directorymensagem; no entanto, ainda não consigo executar os serviços após a rede estar online. Eu tentei ligar network.target, network-online.targete systemd-networkd-wait-online.service, colocando minhas unidades de depender de cada um deles, sem sucesso. Quando verifico o status da unidade vinculada no modo de usuário, todas elas estão mortas, 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.targetativo 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.
Lev Levitsky
fonte
Espero que você tenha uma resposta.
@Deleteme Obrigado, acho que encontrei a causa disso (consulte a atualização), mas não como resolver o problema.
Lev Levitsky
Você encontrou uma solução para esse problema? Além disso, observe que você enfatiza que apenas algumas unidades vinculadas estão mortas. Quais são os que funcionaram e como eles diferem?
Sparhawk
@ Sparhawk infelizmente não. Como solução alternativa, eu apenas uso temporizadores definidos para vários segundos após a inicialização. A questão tem um exemplo: o destino online da rede fica ativo após a vinculação e o destino da rede não.
Lev Levitsky
Talvez eu entenda mal, mas estou procurando algo para disparar toda vez que a rede é retomada, para verificar meu e-mail depois de retomar a suspensão. Eu pensei que este seria o caminho para fazê-lo. Eu vejo os exemplos agora. Pensei que você quisesse dizer que alguns serviços personalizados foram disparados e outros não. No entanto, agora vejo que você está falando sobre as versões de usuário dos destinos de rede.
Sparhawk

Respostas:

3

Como você não pode depender de um serviço do sistema, sua única solução é fornecer um serviço ao usuário que detecte se a rede está online. (Ou faça os serviços do sistema de serviços.) Os detalhes de um serviço de usuário "detect-online" dependeriam da sua definição de "online". Pode esperar um ping para 8.8.8.8, por exemplo. Ou para que uma resolução de nomes DNS seja bem-sucedida. Por exemplo, em uma situação semelhante ao vpnc, espero que um ping em um IP vpn seja bem-sucedido.

Em seguida, você pode fazer com que seus serviços de usuário dependam (após =) do serviço de usuário online 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
Stuart Gathman
fonte
Obrigado, isso parece razoável e simples o suficiente. Mas se 10 usuários habilitarem o meu serviço de usuário, haverá 10 instâncias executando ping no mesmo servidor simultaneamente, o que parece um pouco redundante. Na prática, isso provavelmente não está em questão, mas eu estava perguntando isso na esperança de obter um único "sinalizador online" disponível para todos os serviços do usuário. Ainda não foram sugeridas soluções melhores.
Lev Levitsky
1

Eu recomendaria testar algo como isto:

# /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
fonte
4
Mas este é um serviço do sistema e estou tentando configurar um serviço do usuário.
Lev Levitsky