Запуск скрипта при завершении работы до отключения сети

Запуск скрипта при завершении работы до отключения сети

Я хотел бы запустить скрипт, когда мой компьютер (Ubuntu 22.04) выключается, но при этом сеть все еще доступна.

Совет вэта темалюбезно объяснил, как создать файл службы systemd, который будет запускаться при завершении работы, и скрипт действительно запустился, но скрипт не смог выполнить задачу, требующую доступа к сети, поэтому я предполагаю, что сетевое взаимодействие уже было отключено.

Если найдены различные темы (например,Вот этот) о том, как убедиться, что скрипт запущен до отключения сети, но все они, похоже, давали немного разные советы. Я пробовал различные перестановки Before=network-online.target, After=network-online.target и Requires=network-online.target, но ни одна из них не сработала.

Кто-нибудь знает, как убедиться, что скрипт может работать, пока сеть доступна?

Кстати, я не привязан к тому, чтобы делать это как системную работу. Я предполагал, что это будет лучшим способом сделать это, но если есть другой способ достичь того же самого, то это было бы прекрасно.

решение1

Не знаю, поможет ли это, но рассмотрите возможность просмотра файлов systemd .target. Это то, что systemd на самом деле запускает при завершении работы. Вот ссылка.

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

Файлы .target находятся /usr/lib/systemd/systemвместе с файлами .service. Если бы это был я, я бы делал это на виртуальной машине, где я могу легко откатить снимок ;)

решение2

Хорошо, я еще немного поэкспериментировал и добился прогресса, но пока еще не решил проблему.

Оказывается, сеть работает, если у меня есть After=network.target в файле службы. Похоже, что не работает разрешение имен. Так что если я запускаю взаимодействие с удаленным компьютером, указав имя хоста удаленного компьютера, то оно не работает, но если я указываю его, используя его IP-адрес, то оно работает.

Я надеялся, что смогу исправить это, указав After=network.target nss-lookup.target, но это не помогло.

Есть идеи, что еще я могу попробовать?

решение3

Навскидку, почему бы не сделать bash-скрипт:

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

Выключение не должно выполняться до тех пор, пока «Ваши команды» не будут выполнены.

Скрипт можно назвать «myshutdown» и даже присвоить ему псевдоним системной команды.

(Мне кажется, что это слишком упрощенно, и я уверен, что кто-нибудь укажет мне на ошибки!) (Спасибо за редактирование кода, «Марко»)

решение4

Ключом к пониманию того, как остановить службу при отключении до потери сети, является знание того, чтопорядок выключения - это обратный порядку запуска. Поэтому ваша служба должна начатьсяпосле network-online.targetпри этом также имея зависимость от network-online.target, поскольку он требует, чтобы сеть была включена. Кроме того, есть ExecStart=и ExecStop=действия, которые вы можете определить. Поскольку вы хотите, чтобы скрипт запускался при завершении работы, то есть при остановке службы, вы хотите определить ExecStop=указание на ваш скрипт.

Чтобы настроить это, сделайте следующее:

  • в[Единица]раздел, создаем Requires=network-online.targetзависимость
  • Установите порядок After=network-online.target.
  • в[Услуга]раздел, не определяйте ExecStart=действие.
  • Установите RemainAfterExit=true, поскольку мы не создали ExecStart=действие.
  • Наконец, создайте ExecStop=действие, указывающее на ваш скрипт, например ExecStop=/home/username/bin/testscript.sh.

Помнить,порядок выключения - это обратный порядку запуска. Поэтому, когда ваша служба остановлена, ваш скрипт, который находится в ExecStop=, будет запущен. И поскольку мы запустили эту службупосле network-online.target, он будет закрытдовсе службы network-online.targetотключены.

В качестве примера...

Вот простой тестовый скрипт, который использует curlдля получения вашего публичного IP-адреса. Таким образом, для корректной работы требуется DNS.

#!/bin/bash

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

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

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

Далее создайте файл службы/юнита systemd в /etc/systemd/system. Я назвал его 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

Сообщите systemd, чтобы он прочитал наш файл:

sudo systemctl daemon-reload

Включить услугу:

sudo systemctl enable testservice.service

Затем перезагрузите систему, и вы увидите, что файл /home/username/ipaddressобновится с указанием временной метки при завершении работы и вашего публичного IP-адреса.

Связанный контент