web-dev-qa-db-ja.com

Systemd:シャットダウン時にのみスクリプトを実行する方法(再起動時ではない)

シャットダウン/再起動時にスクリプトを実行するための解決策はたくさんありますが、シャットダウン時にのみスクリプトを実行したいです。

スクリプトを/ usr/lib/systemd/systemd-shutdownに入れて、$ 1パラメータを確認しようとしました here のように見えますが、機能しません。

何か案は ?

システム:gnome-Shellを使用したarchlinux

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

私は最終的にそれを行う方法を見つけました。

これは少しハッカ的な考えですが、機能します。

私はこのスレッドの一部を使用しました: https://stackoverflow.com/questions/25166085/how-can-a-systemd-controled-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

これは、shudown/reboot/halt/whateverで実行されます。 (有効にすることを忘れないでください)

そして私のスクリプトでは/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に送信され、画面がシャットダウンされます。

9
benoit2600

systemd.specialのマニュアルページによると、Before=poweroff.targetを使用する必要があります。

poweroff.target

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
5
ILMostro_7

ここで回答を読むと、systemdの動作について多くの誤解があるようです。まず、ターゲットを除外するために競合を使用しないでください。競合するサービスが同時に実行されないようにすることは重要です。

ユニットに別のユニットのConflicts =設定がある場合、前者を開始すると後者が停止し、逆も同様です。

ユニットとは、到達するターゲットではなく、特定のサービスを起動するための.serviceファイルメントを意味します。つまり、Conflicts=reboot.targetはせいぜい意味がなく、最悪の場合、再起動できなくなります。これを行わないでください。再起動時にこれを実行しないという意味ではありません。これは、タイミングとsystemdがこの競合の誤った使用をどのように解釈するかに応じて、このサービスまたはreboot.targetのいずれかを中止することを意味します。

以下は、再起動ではなくシャットダウン時にのみ実行される、現在セットアップされているユニット(別名.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実行レベル0と同等です。 halt.targetは、systemdが使用する代替のシャットダウンパスで、再起動でも到達できません。インストールセクションは、poweroff.targetまたはhalt.targetに到達したと見なされる前に完了する必要があるリストにこのサービスを追加するようにsystemdに指示します。

このサービスはシステムにインストールされ、実行されています。