当我 sudo 时,无法在 shell 脚本中运行“kill -- -$$”

当我 sudo 时,无法在 shell 脚本中运行“kill -- -$$”

我有一个启动几个后台子进程的 shell 脚本。我希望它们始终运行 - 除非父进程退出或被杀死(所以我让子进程处于一个循环中,如果退出则总是重新启动)。

如果我直接执行这个脚本,似乎效果相对较好。但一旦我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

显然,因为它没有杀死孩子们,所以他们仍然在运行,并仍然在我的 shell 中输出。当我不使用 sudo 时,效果很好。

它似乎是kill -- -$$我脚本的陷阱和“按键监视器”部分。注释掉其中一个并不能解决另一个问题。

有谁知道我该如何解决这个问题?我只是希望它能在大多数情况下工作(至少,无论是否需要 sudo)。

谢谢!

答案1

是的kill -- -"$pgid",那就是它必须是一个过程团体ID。仅当 shell 是进程组领导者时才有效,但从交互式 shellkill -- -"$$"运行时则不然: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

这是杀死你自己的进程组的命令。

无论如何,只有从交互式 shell(执行作业控制)单独调用脚本时,这才是有效的做法。

另请注意,在:

(the-script; echo "$?")

或者:

the-script | cmd

第一种情况或cmd第二种情况中的子 shell 也放置在同一进程组中,因此也会被杀死kill 0

相关内容