スクリプトがsystemdから呼び出されたか、ユーザーから呼び出されたかを確認するにはどうすればよいですか?
古い学校のデーモン用のサービスを作成しました。 systemdに切り替えたばかりで、私の管理者の一部はrcスクリプトを直接呼び出したいと思っています。マシンを再起動した場合、これはうまく機能しません。新しく起動したデーモンはサービスのcgroupの一部ではないため、SystemdはPIDFile=
を尊重しません。
サービスファイルとrc_scriptを追加しました。スクリプトを使用するには、ユーザーがfoobaruser
である必要があるため、ユーザーIDで区別することはできません。
Systemdは削除されたpidファイルからこれを認識するため、サービスの停止に問題があります。
では、スクリプトがsystemdから呼び出されたかどうかを確認するにはどうすればよいですか?
[Unit]
Description=Foobar Service
After=syslog.target network.target
[Service]
Type=forking
User=foobaruser
LimitNOFILE=60000
LimitNPROC=8000
TasksMax=8000
PIDFile=/local/foobar/foo.pid
ExecStart=/opt/foobar/rc_script start
ExecStop=/opt/foobar/rc_script stop
TimeoutSec=100
TimeoutStopSec=300
KillMode=none
RemainAfterExit=no
Environment=LANG=de_DE.UTF-8
[Install]
WantedBy=multi-user.target
#!/bin/bash
case $1 in
start)
VAR_IS_SYSTEMD=$( ... script to check if bash is run from systemd ... )
if [ "$VAR_IS_SYSTEMD" = false ] ; then
Sudo systemctl start foobar.service
exit
fi
# start service within systemd
;;
stop)
# stop service
;;
esac
スクリプトをまったく呼び出さないようにサービスを書き直そうとする他のポスターに同意します(管理者がスクリプトを使い続けたい場合は問題ありませんが、systemdサービスには36のオプションすべてが必要ですか?)–それもまたそうではありませんスクリプトがsystemdから呼び出されたかどうかを検出するのは困難です。
systemd v232には、ユニットの呼び出しIDの概念が追加されました。これは、$INVOCATION_ID
環境変数でユニットに渡されます。設定されているかどうかを確認できます。
systemd v231 +は、stdoutまたはstderrがジャーナルに接続されているサービスの$JOURNAL_STREAM
変数を設定します。これは、サービスに当てはまるようです。そのため、systemd v231を使用している場合は、その変数を確認することもできます。 (v232 +では、$INVOCATION_ID
が間違いなく良い選択です。)
古いsystemdバージョンでは、常に存在する環境変数があるとは思いませんが、次のようなものをサービスに追加することにより、もちろん自分で定義することができます。
Environment=LAUNCHED_BY_SYSTEMD=1
簡単な解決策は、systemdが起動する別のスクリプトを使用することです。/opt/foobar/rc_scriptはsystemctl start foobar.service
およびsystemctl stop foobar.service
を呼び出すだけです。
Suseは$SYSTEMD_NO_WRAP
を使用していますが、それがsystemd標準なのかSuse固有なのかわかりません。
if test -z "$SYSTEMD_NO_WRAP"; then
...
/usr/bin/systemctl [start|stop] xxx.service
「Amazon Linux 2」と「Red Hat Enterprise Linux 7」の場合、解決策を見つけました。
これらのLinuxシステムでは、システムプロセスPID=1
はcomm=systemd
。 systemdで開始されたスクリプトの親ID PPID
は1
。
これが当てはまらない他のLinuxシステムがあるかもしれません。
#!/bin/bash
VAR_IS_SYSTEMD_SYSTEM=$( [[ $(ps -o comm -p 1 --no-headers | tr -d ' ') == "systemd" ]] && echo true )
echo VAR_IS_SYSTEMD_SYSTEM = ${VAR_IS_SYSTEMD_SYSTEM}
VAR_IS_DAEMON_SCRIPT=$( [[ "${PPID}" == "1" ]] && echo true )
echo VAR_IS_DAEMON_SCRIPT = ${VAR_IS_DAEMON_SCRIPT}
if [[ "${VAR_IS_SYSTEMD_SYSTEM}" = true ]] && [[ "${VAR_IS_DAEMON_SCRIPT}" = true ]]; then
echo "You are a systemd Daemon Script"
else
echo "You are a normal Script"
fi
使用する要素/コマンド:
ps -o comm -p 1 --no-headers
プロセス1のコマンド名を取得する
tr -d ''
Psコマンドから書式空白を削除する
「$ {PPID}」
Bashプロセスの親PID