为什么kill不能在脚本中工作,但可以在终端中工作?

为什么kill不能在脚本中工作,但可以在终端中工作?

我有以下设计的脚本来说明我的问题:

#!/bin/bash
set -eux
sudo sleep 120 &
spid=$!
sleep 1
sudo kill $spid
wait $!

这将打印

$ ./test.sh 
+ spid=21931
+ sleep 1
+ sudo sleep 120
+ sudo kill 21931
+ wait 21931

然后坚持下去,wait直到sleep 120时间到。但是,当我sudo kill 21931从另一个终端运行时,睡眠进程立即被终止。我预计sudo kill $spid脚本中的行也会立即终止睡眠进程。为什么这不起作用以及如何使其起作用?

(可能相关:我在 Ubuntu 15.10 上看到了 bash 4.3.42 和 dash 0.5.7 的这种行为。)

答案1

原因可以在源代码须藤:

/*
 * 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.
 */

答案2

差异可能在于 /etc/sudoers 文件中。也许您的用户可以在一台机器上使用 nopasswd 运行kill,但不能在另一台机器上运行。

答案3

我确认这种奇怪的行为也发生在 Ubuntu 17.10 bash 4.4.12(1)-release (x86_64-pc-linux-gnu) 上。

我无法找出真正的原因,但似乎与过程信号有关。默认情况下,kill发出15 – TERM代表软终止的信号。但是,如果我使用 hard 9 – KILL,睡眠进程会立即被终止。

#!/bin/bash
set -eux
sudo sleep 120 &
spid=$!
sleep 1
sudo kill -9 $spid
wait $!

打印出来

$ ./test.sh 
+ spid=4342
+ sleep 1
+ sudo sleep 120
+ sudo kill -9 4342
./test.sh: line 6:  4342 Killed                  sudo sleep 120
+ wait 4342

答案4

我遇到了类似的问题并降落在这里。其他答案没有帮助。我的脚本按照以下方式将 ID 通过管道传输到 Kill 中:

echo $some_output | awk '{print $1}' | xargs kill -9

这可以从终端运行,但不能从脚本运行。找到这个答案后说Kill 不会从 stdin 读取 PID,我将脚本更改为此并解决了问题:

pids=`echo $some_output | awk '{print $1}'`

for p in $pids; do
    echo "Killing $p"
    kill -9 $p
done

希望这对像我一样来到这里的人有所帮助!

相关内容