Executando um script no desligamento antes que a rede caia

Executando um script no desligamento antes que a rede caia

Gostaria de executar um script quando meu computador (Ubuntu 22.04) desligar, mas enquanto a rede ainda estiver disponível.

O conselho emeste tópicoexplicou de forma útil como criar um arquivo de serviço systemd que seria executado no desligamento, e o script realmente foi executado, mas o script não foi capaz de concluir uma tarefa que exigia acesso à rede, então presumo que a rede já tenha sido desligada.

Se forem encontrados vários tópicos (por exemploEste) sobre como garantir que um script fosse executado antes do encerramento da rede, mas todos pareciam ter conselhos ligeiramente diferentes. Tentei várias permutações de Before=network-online.target, After=network-online.target e Requires=network-online.target, mas nenhuma delas pareceu funcionar.

Alguém sabe como garantir que o script possa ser executado enquanto a rede ainda estiver disponível?

Aliás, não estou comprometido em fazer isso como um trabalho do systemd. Presumi que essa seria a melhor maneira de fazer isso, mas se houver outra maneira de conseguir a mesma coisa, tudo bem.

Responder1

Não sei se isso vai ajudar, mas considere dar uma olhada nos arquivos .target do systemd. Isto é o que o systemd realmente executa ao desligar. Aqui está um link.

https://documentation.suse.com/smart/linux/html/reference-managing-systemd-targets-systemctl/index.html

shutdown.target
       A special target unit that terminates the services on system
       shutdown.

       Services that shall be terminated on system shutdown shall add
       Conflicts= and Before= dependencies to this unit for their service
       unit, which is implicitly done when DefaultDependencies=yes is set
       (the default).

Os arquivos .target acompanham /usr/lib/systemd/systemos arquivos .service. Se fosse eu, estaria fazendo isso em uma VM onde posso facilmente reverter um instantâneo;)

Responder2

OK, brinquei um pouco mais e fiz progressos, mas ainda não resolvi o problema.

Acontece que a rede funciona, mais ou menos, se eu tiver After=network.target no arquivo de serviço. Parece que a resolução de nomes não está funcionando. Portanto, se eu executar a interação com o computador remoto especificando o nome do host do computador remoto, ela não funcionará, mas se eu especificar usando seu endereço IP, ela funcionará.

Eu esperava poder consertar isso com After=network.target nss-lookup.target, mas isso não resolveu.

Alguma idéia do que mais eu poderia tentar?

Responder3

Pensando bem na minha cabeça antiga e careca, por que não fazer um script bash:

#!/bin/bash
Your Commands;
shutdown -h now

O desligamento não deve ser executado até que 'Seus comandos' tenham concluído a execução.

O script pode ser chamado de 'myshutdown' e até mesmo ter um alias para o comando do sistema.

(Parece muito simplista para mim, e tenho certeza que alguém apontará meus erros!) (Obrigado pela edição para arrumar o código 'Marco')

Responder4

A chave para entender como fazer com que um serviço pare no desligamento antes de perder a rede é saber quea ordem de desligamento é a ordem reversa de inicialização. Portanto, seu serviço deve começardepois network-online.targetao mesmo tempo que depende de network-online.target, porque exige que a rede esteja ativa. Além disso, existem ExecStart=ações ExecStop=que você pode definir. Como você deseja que o script seja executado no desligamento, que é quando o serviço é interrompido, você deseja definir ExecStop=o apontamento para o seu script.

Para configurar isso, faça o seguinte:

  • No[Unidade]seção, crie uma Requires=network-online.targetdependência
  • Defina a ordem como After=network-online.target.
  • No[Serviço]seção, não defina uma ExecStart=ação.
  • Set RemainAfterExit=true, porque não criamos uma ExecStart=ação.
  • Por fim, crie uma ExecStop=ação apontando para o seu script, como ExecStop=/home/username/bin/testscript.sh.

Lembrar,a ordem de desligamento é a ordem reversa de inicialização. Portanto, quando seu serviço for interrompido, seu script, que está colocado em ExecStop=, será executado. E porque iniciamos este serviçodepois network-online.target, será desligadoantestodos os serviços network-online.targetestão desligados.

Como um exemplo...

Aqui está um script de teste simples usado curlpara obter seu endereço IP público. Como tal, o DNS é necessário para que isso funcione corretamente.

#!/bin/bash

# NAME: testscript.sh
# PATH: /home/username/bin

NOW=`date`
IP=`curl -s https://ipinfoio/ip`

echo $NOW $IP >> /home/username/ipaddresses

Em seguida, crie um arquivo de serviço/unidade systemd no formato /etc/systemd/system. Eu nomeei isso testservice.service.

[Unit]
Description:Test service to execute at shutdown prior to losing network
Requires=network-online.target
After=network-online.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/username/bin/testscript.sh

[Install]
WantedBy=multi-user.target

Diga ao systemd para ler nosso arquivo:

sudo systemctl daemon-reload

Habilite o serviço:

sudo systemctl enable testservice.service

Em seguida, reinicie o sistema e você verá que o arquivo /home/username/ipaddressserá atualizado com um carimbo de data/hora no desligamento e seu endereço IP público.

informação relacionada