
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.
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/system
os 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.target
ao 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.target
dependê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 umaExecStart=
ação. - Por fim, crie uma
ExecStop=
ação apontando para o seu script, comoExecStop=/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.target
estão desligados.
Como um exemplo...
Aqui está um script de teste simples usado curl
para 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/ipaddress
será atualizado com um carimbo de data/hora no desligamento e seu endereço IP público.