向过程组的所有成员发送信号的最佳方式是什么?

  • 回答 (2)
  • 关注 (0)
  • 查看 (42)

我想杀死整个进程树。使用任何通用脚本语言来做这件事的最好方法是什么?我正在寻找一个简单的解决方案。

以往V以往V提问于
akjok54stay hungry stay foolish回答于
pkill -TERM -P 27888

这将终止具有父进程ID 27888的所有进程。

或更健壮:

CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS

该计划杀死33秒后,礼貌地要求进程终止。

人生的旅途辣鸡前端回答于

使用进程组ID()来杀死属于同一进程树的所有进程PGID

kill -- -$PGID     使用默认信号(TERM= 15)
kill -9 -$PGID     使用信号KILL(9)

您可以PGID从同一个进程树的任何Process-ID(PID)中检索

kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*')   (信号TERM)
kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*')   (信号KILL)

特别感谢唐加拉雀和Speakus的捐款$PID剩余空间和OSX的兼容性。

说明

kill -9 -"$PGID"=>发送信号9(KILL)给所有的孩子和孙子...

PGID=$(ps opgid= "$PID")=> 从树的任何Process-ID中检索Process-Group-ID,而不仅仅是Process-Parent-ID。的变型就是其中可以被替换。但: ps opgid= $PIDps -o pgid --no-headers $PIDpgidpgrp

ps在PID小于5位数字时插入前导空格,并且如唐纳格所注意的那样插入右对齐。您可以使用:

PGID=$(ps opgid= "$PID" | tr -d ' ')

ps从OSX总是打印标题,因此Speakus建议:

PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"

grep -o [0-9]* 仅打印连续的数字(不打印空格或字母标题)。

更多的命令行

PGID=$(ps -o pgid= $PID | grep -o [0-9]*)
kill -TERM -"$PGID"  # kill -15
kill -INT  -"$PGID"  # correspond to [CRTL+C] from keyboard
kill -QUIT -"$PGID"  # correspond to [CRTL+\] from keyboard
kill -CONT -"$PGID"  # restart a stopped process (above signals do not kill it)
sleep 2              # wait terminate process (more time if required)
kill -KILL -"$PGID"  # kill -9 if it does not intercept signals (or buggy)

局限性

正如davide和Hubert Kario所注意到的那样,当kill一棵属于同一棵树的进程被调用时,kill在终止整个树木杀死之前有可能自杀。

因此,请确保使用具有不同Process-Group-ID的进程运行该命令。

很长的故事

> cat run-many-processes.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./child.sh background &
./child.sh foreground
echo "ProcessID=$$ ends ($0)"
> cat child.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./grandchild.sh background &
./grandchild.sh foreground
echo "ProcessID=$$ ends ($0)"
> cat grandchild.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
sleep 9999
echo "ProcessID=$$ ends ($0)"

在后台使用'&'运行进程树

> ./run-many-processes.sh &    
ProcessID=28957 begins (./run-many-processes.sh)
ProcessID=28959 begins (./child.sh)
ProcessID=28958 begins (./child.sh)
ProcessID=28960 begins (./grandchild.sh)
ProcessID=28961 begins (./grandchild.sh)
ProcessID=28962 begins (./grandchild.sh)
ProcessID=28963 begins (./grandchild.sh)
> PID=$!                    # get the Parent Process ID
> PGID=$(ps opgid= "$PID")  # get the Process Group ID
> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    28969 Ss   33021   0:00 -bash
28349 28957 28957 28349 pts/3    28969 S    33021   0:00  \_ /bin/sh ./run-many-processes.sh
28957 28958 28957 28349 pts/3    28969 S    33021   0:00  |   \_ /bin/sh ./child.sh background
28958 28961 28957 28349 pts/3    28969 S    33021   0:00  |   |   \_ /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3    28969 S    33021   0:00  |   |   |   \_ sleep 9999
28958 28963 28957 28349 pts/3    28969 S    33021   0:00  |   |   \_ /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3    28969 S    33021   0:00  |   |       \_ sleep 9999
28957 28959 28957 28349 pts/3    28969 S    33021   0:00  |   \_ /bin/sh ./child.sh foreground
28959 28960 28957 28349 pts/3    28969 S    33021   0:00  |       \_ /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3    28969 S    33021   0:00  |       |   \_ sleep 9999
28959 28962 28957 28349 pts/3    28969 S    33021   0:00  |       \_ /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3    28969 S    33021   0:00  |           \_ sleep 9999
28349 28969 28969 28349 pts/3    28969 R+   33021   0:00  \_ ps fj

这个命令pkill -P $PID并没有杀死孙子:

> pkill -P "$PID"
./run-many-processes.sh: line 4: 28958 Terminated              ./child.sh background
./run-many-processes.sh: line 4: 28959 Terminated              ./child.sh foreground
ProcessID=28957 ends (./run-many-processes.sh)
[1]+  Done                    ./run-many-processes.sh
> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    28987 Ss   33021   0:00 -bash
28349 28987 28987 28349 pts/3    28987 R+   33021   0:00  \_ ps fj
    1 28963 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28962 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28961 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28960 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999

这个命令kill -- -$PGID杀死了包括孙子在内的所有进程。

> kill --    -"$PGID"  # default signal is TERM (kill -15)
> kill -CONT -"$PGID"  # awake stopped processes
> kill -KILL -"$PGID"  # kill -9 to be sure
> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    29039 Ss   33021   0:00 -bash
28349 29039 29039 28349 pts/3    29039 R+   33021   0:00  \_ ps fj

结论

我注意到在这个例子中PID和PGID是相等的(28957)。

这就是为什么我原本以为kill -- -$PID够了。但是,如果进程在一个进程ID中产生,Makefile则进程ID与组ID不同。

我认为kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)从另一个组ID(另一个进程树)调用时,杀死整个进程树是最简单的技巧。

所属标签

可能回答问题的人

  • 西风

    renzha.net · 站长 (已认证)

    7 粉丝1 提问12 回答
  • 四无君

    0 粉丝0 提问3 回答
  • HKC

    红客学院 · 创始人 (已认证)

    26 粉丝7 提问2 回答
  • o o

    3 粉丝490 提问2 回答

扫码关注云+社区

领取腾讯云代金券