Systemd: как выполнить скрипт только при завершении работы (не при перезагрузке)

Systemd: как выполнить скрипт только при завершении работы (не при перезагрузке)

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

Я попробовал поместить свой скрипт в /usr/lib/systemd/systemd-shutdown и проверить параметр $1, как показаноздесь, но это не работает.

Есть идеи ?

система: archlinux с gnome-shell

$systemctl --version                                                                                                                                                                                 
systemd 229
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN

решение1

Я наконец нашел, как это сделать.

Это немного банальная идея, но она работает.

Я использовал часть этой ветки:https://stackoverflow.com/questions/25166085/how-can-a-systemd-controlled-service-distinguish-between-shutdown-and-reboot

и эта ветка: Как запустить скрипт с помощью systemd прямо перед выключением?

Я создал эту услугу/etc/systemd/system/shutdown_screen.service

[Unit]
Description=runs only upon shutdown
Conflicts=reboot.target
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/bin/bash /usr/local/bin/shutdown_screen
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Который будет выполнен при выключении/перезагрузке/остановке/и т.д. (не забудьте включить его)

И в свой сценарий /usr/local/bin/shutdown_screen я вставил следующее:

#!/bin/bash
# send a shutdown message only at shutdown (not at reboot)    
/usr/bin/systemctl list-jobs | egrep -q 'reboot.target.*start' || echo "shutdown" | nc 192.168.0.180 4243 -w 1

Что отправит сообщение о выключении на мой Arduino, который выключит мой экран.

решение2

Согласно systemd.specialman-странице, вам следует использовать Before=poweroff.target.

poweroff.цель

A special target unit for shutting down and powering off the system.

Applications wanting to power off the system should start this unit.

runlevel0.target is an alias for this target unit, for compatibility with SysV.

Кроме того, как я уже упоминал в своем комментарии, вам следует помещать пользовательские скрипты в /etc/systemd/system/. /usr/lib/systemd/system/Каталог предназначен для использования для системных скриптов.

Итак, может быть что-то вроде этого:

[Unit]
Description=runs only upon shutdown
DefaultDependencies=no
Conflicts=reboot.target
Before=shutdown.target
Requires=poweroff.target

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/usr/local/bin/yourscript
RemainAfterExit=yes

решение3

Из прочитанных здесь ответов следует, что существует много недопонимания относительно того, как работает systemd. Во-первых, не используйте конфликты для исключения цели. Следует избегать одновременного запуска конфликтующих служб.

Если у блока есть настройка Conflicts= на другом блоке, запуск первого блока остановит последний и наоборот.

Unit означает файл .service, предназначенный для запуска определенной службы, а не цель, к которой нужно достичь. Другими словами, Conflicts=reboot.targetв лучшем случае это бессмысленно, а в худшем — не позволит вам перезагрузиться. Не делайте этого. Это не значит, что не нужно запускать это при перезагрузке. Это значит, что нужно прервать либо эту службу, либо reboot.target в зависимости от времени и того, как systemd интерпретирует это ошибочное использование конфликтов.

Вот пример текущего настроенного модуля (также известного как файл .service), который запускается только при выключении, а не при перезагрузке:

[Unit]
Description=Play sound
DefaultDependencies=no
Before=poweroff.target halt.target

[Service]
ExecStart=/usr/local/bin/playsound.sh
ExecStop=/usr/local/bin/playsound.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=poweroff.target halt.target 

poweroff.target эквивалентен старому systemv run level0, который достигается только при выключении. halt.target — это альтернативный путь выключения, используемый systemd, который также недоступен при перезагрузке. Раздел install сообщает systemd о необходимости добавить эту службу в список, который должен быть завершен до poweroff.targetили halt.targetбудет считаться достигнутым.

Эта служба установлена ​​и работает в моей системе.

решение4

Я протестировал большую часть поста здесь и на разных сайтах. Единственный, который действительно работал только при перезагрузке (не при загрузке снова - но фактически не работал при shutdown-halt-poweroff) - это пост @benoit2600 . его второй пост/решение

Но после тестирования я обнаружил, что вы можете использовать в Unit все 4 цели и они будут работать, когда один из них фактически используется ТОЛЬКО. Остальное в соответствии с его и вашими потребностями В "ExecStop=mycommand" я просто ввел свою прямую команду (так как мне не нужен был полный bash)

[Unit]
Conflicts=reboot.target poweroff.target halt.target shutdown.target

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