複数のバックグラウンドサブプロセスを開始するシェルスクリプトがあります。親プロセスが終了または終了しない限り、常に実行したいと思います。したがって、子プロセスが終了すると、常に再起動されるループに子プロセスがあります。
このスクリプトを直接実行してみると、比較的うまくいくようです。ただし、これを行うと、sudo
他のプロセスが正しくクリーンアップされません。
#!/bin/bash
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
# Start first background thing
while true;
do
sleep 1
echo "SOME PROCESS RUNNING IN THE BACKGROUND"
echo "SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES"
sleep 5
done &
# Start second background thing
while true;
do
sleep 3
echo "ANOTHER ONE..."
sleep 3
done &
# Wait for quit keypress
while true
do
echo "Press 'Q' to quit"
read -rsn1
if [ $REPLY == "q" ] || [ $REPLY == "Q" ]; then
echo "Are you sure? [Y/N]"
read -rsn1
if [ $REPLY == "y" ] || [ $REPLY == "Y" ]; then
kill -- -$$
exit
fi
fi
echo ""
sleep 1
done
# Wait
wait
sudo 時に CTRL+C を押すか「Q」を押して終了すると、親 (基本) プロセスは終了しますが、子プロセスは終了せず、次のエラーが発生します。
adam@TG-BBCAM-01:~ $ sudo ./temp.sh
Press 'Q' to quit
Are you sure? [Y/N]
./temp.sh: line 31: kill: (-29098) - No such process
./temp.sh: line 1: kill: (-29098) - No such process
adam@TG-BBCAM-01:~ $ SOME PROCESS RUNNING IN THE BACKGROUND
SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES
ANOTHER ONE...
SOME PROCESS RUNNING IN THE BACKGROUND
SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES
ANOTHER ONE...
SOME PROCESS RUNNING IN THE BACKGROUND
SHOULD AUTO-RESTART IF IT GETS KILLED OR CRASHES
ANOTHER ONE...
SOME PROCESS RUNNING IN THE BACKGROUND
明らかに、それは子供を殺さなかったので、彼らはまだ実行中であり、私のシェルから出力を続けています。 sudoを使わないとうまくいきます。
kill -- -$$
それは私のスクリプトの落とし穴であり、「キーモニター」部分のようです。 1つをコメントアウトしても、他の問題は解決されません。
この問題をどのように解決できるかを知っている人はいますか?私はそれがほとんどの場合に動作することを願っています(少なくともsudoが必要かどうかは)。
ありがとうございます!
答え1
うんkill -- -"$pgid"
、それは一つのプロセスでなければなりません。グループID。これは、シェルがプロセスグループリーダーの場合にのみ機能しますが、kill -- -"$$"
対話型シェルで実行している場合は機能しません。sudo
$ sudo bash -c 'ps -j; exit'
PID PGID SID TTY TIME CMD
26786 26786 29719 pts/39 00:00:00 sudo
26794 26786 29719 pts/39 00:00:00 bash
26795 26786 29719 pts/39 00:00:00 ps
sudo
ではなくプロセスグループリーダーになりますbash
。
したがって、次のことを行うkill -- -"$(ps -o pgid= -p "$$")"
か、単に行う必要があります。
kill 0
これは自分のプロセスグループを終了するコマンドです。
それにもかかわらず、これはスクリプトが対話型シェルから個別に呼び出される場合(ジョブ制御の実行)にのみ有効です。
以下も参考にしてください。
(the-script; echo "$?")
または:
the-script | cmd
最初またはcmd
2番目のケースのサブシェルも同じプロセスグループに配置されるため、同様に終了しますkill 0
。