为什么这种杀戮没有';不能在这个Bash脚本中工作,但只能在脚本之外工作?

为什么这种杀戮没有';不能在这个Bash脚本中工作,但只能在脚本之外工作?,bash,shell,sh,kill,Bash,Shell,Sh,Kill,下面是一个人为的示例,演示了这种效果,并且必须使用root运行。它在后台执行ping进程并试图杀死它 #!/bin/bash # Ensure that there is no ping process before we begin. killall ping sudo ping google.com > /dev/null & PID=$! sleep 0.5 kill $PID echo "Exit code of kill $PID: $?" # Check th

下面是一个人为的示例,演示了这种效果,并且必须使用root运行。它在后台执行ping进程并试图杀死它

#!/bin/bash

# Ensure that there is no ping process before we begin.
killall ping

sudo ping google.com > /dev/null &
PID=$!

sleep 0.5

kill $PID
echo "Exit code of kill $PID: $?"

# Check the running ping processes. There should be no ping
# process if the above `kill $PID` worked correctly.
ps aux | grep -v grep | grep ping
但是,即使
kill
的返回代码为0,脚本也无法终止进程。下面是一个示例输出

$ bash test.sh
Exit code of kill 16516: 0
root     16516  0.0  0.0  14956  2212 pts/2    S    13:22   0:00 sudo ping google.com
root     16518  1.0  0.0  13112  1292 pts/2    S    13:22   0:00 ping google.com
我注意到,如果我拿出
sudo
,它就会正确地杀死它。为什么会这样?不过我怀疑
sudo
的子进程不知怎么搞砸了

更新1:

更奇怪的是。如果我在脚本之后执行相同的
kill
命令,它就会工作

$ bash test.sh
Exit code of kill 16631: 0
root     16631  3.0  0.0  14956  2212 pts/2    S    13:29   0:00 sudo ping google.com
root     16633  0.0  0.0  13112  1292 pts/2    S    13:29   0:00 ping google.com
$ ps aux | grep -v grep | grep ping
root     16631  0.5  0.0  14956  2212 pts/2    S    13:29   0:00 sudo ping google.com
root     16633  0.0  0.0  13112  1292 pts/2    S    13:29   0:00 ping google.com
$ kill 16631
$ ps aux | grep -v grep | grep ping
$
$ kill 16631
-bash: kill: (16631) - No such process
$

这是因为控制
sudo
进程不传播来自其自身进程组()的信号:


在脚本外部执行命令时,在单独的进程组中运行该命令,因此信号将被中继。

因为PID所有者是root,但您将作为不同的用户终止它。尝试
sudo kill$pid
在没有睡眠的情况下,在它有机会开始
ping
@之前杀死
sudo
。@另一个家伙哦,我明白了,这似乎解释了为什么睡眠能起作用。虽然我仍然不明白为什么kill还不起作用…@MattClark不完全是你建议的,但是即使脚本以root运行,仍然会发生。我更新了这个问题。太棒了。我可以复制这个。此外,如果我使用
script-c“kill$PID”
setsid kill$PID
,它确实会按预期终止进程
kill$PID
/bin/kill$PID
不要。你是我的英雄
/*
 * Do not forward signals sent by a process in the command's process
 * group, as we don't want the command to indirectly kill itself.
 * For example, this can happen with some versions of reboot that
 * call kill(-1, SIGTERM) to kill all other processes.
 */
if (USER_SIGNALED(sc->siginfo) && sc->siginfo->si_pid != 0) {
    pid_t si_pgrp = getpgid(sc->siginfo->si_pid);
    if (si_pgrp != -1) {
    if (si_pgrp == ec->ppgrp || si_pgrp == ec->cmnd_pid)
        debug_return;
    } else if (sc->siginfo->si_pid == ec->cmnd_pid) {
        debug_return;
    }
}