sudo時にシェルスクリプトで "kill -- -$$"を実行することはできません。

sudo時にシェルスクリプトで

複数のバックグラウンドサブプロセスを開始するシェルスクリプトがあります。親プロセスが終了または終了しない限り、常に実行したいと思います。したがって、子プロセスが終了すると、常に再起動されるループに子プロセスがあります。

このスクリプトを直接実行してみると、比較的うまくいくようです。ただし、これを行うと、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

最初またはcmd2番目のケースのサブシェルも同じプロセスグループに配置されるため、同様に終了しますkill 0

おすすめ記事