须藤忽略来自同一个脚本发送SIGTERM

问题描述 投票:1回答:2

我试图找出为什么这不起作用:

#!/bin/bash

sudo sleep 60 &
sudo_pid=$!
sudo kill $sudo_pid

我想到的是,kill之后,sudo命令及其子sleep过程将被终止,但他们都没有,见下面的脚本:

#!/bin/bash

sudo sleep 60 &
sudo_pid=$!
sudo kill $sudo_pid

if ps -p $sudo_pid > /dev/null; then
    sudo kill $sudo_pid
else
    echo "No sudo process running"
    exit 1
fi

if ps -p $sudo_pid > /dev/null; then
    echo "sudo (pid $sudo_pid) is still running"
    ps -F $sudo_pid
else
    echo "sudo successfully killed"
fi

当我运行它(与缓存sudo creds)这将产生这样的输出:

jon@ubuntu:~$ ./so.sh 
sudo (pid 46199) is still running
UID         PID   PPID  C    SZ   RSS PSR STIME TTY      STAT   TIME CMD
root      46199  46198  0 14764  3984   3 13:37 pts/0    S+     0:00 sudo sleep 60

剧本完成后(并sudo sleep 60仍在运行),可以用相同的命令来杀死它:

jon@ubuntu:~$ ps -F 46199
UID         PID   PPID  C    SZ   RSS PSR STIME TTY      STAT   TIME CMD
root      46199      1  0 14764  3984   3 13:37 pts/0    S      0:00 sudo sleep 60

jon@ubuntu:~$ sudo kill 46199

jon@ubuntu:~$ ps -F 46199
UID         PID   PPID  C    SZ   RSS PSR STIME TTY      STAT   TIME CMD

jon@ubuntu:~$

我注意到so.sh脚本退出后,为sudo sleep 60父进程ID已经从脚本改为init过程中,我认为这是显著。这也可以从不同的外壳成功击杀sudo sleep 60过程,而so.sh脚本仍在运行。

我还注意到,在脚本中使用sudo kill -ABRT(而不是kill的默认SIGTERM)并成功击杀sudo过程,所以我认为是有事情做与sudo处理SIGTERM的方式。然而,根据该男子页上,我不认为它应该做什么特别的东西:

Signal handling
  When the command is run as a child of the sudo process, sudo will relay
  signals it receives to the command.  The SIGINT and SIGQUIT signals are
  only relayed when the command is being run in a new pty or when the sig‐
  nal was sent by a user process, not the kernel.  This prevents the com‐
  mand from receiving SIGINT twice each time the user enters control-C.

在手册页提到SIGTERM唯一的特殊处理是signals that were sent by the command it is running;不是这里的情况。此外,我改变了ps -F在上面的脚本来ps -o blocked,caught,ignored,pending并输出

sudo (pid 46429) is still running
         BLOCKED           CAUGHT          IGNORED          PENDING
0000000000000000 00000001800b7a07 0000000000000000 0000000000000000

这似乎表明,SIGTERM没有被阻塞或忽略,所以为什么不sudo sleep 60过程遭到停权?

我想出了几种解决方法(setsidsudo -b,杀子sleep过程,而不是父sudo工艺),所以我不是在寻找替代方法的答案。我只是想明白是怎么回事。

如果它的事项:

jon@ubuntu:~$ uname -a
Linux ubuntu 4.13.0-16-generic #19-Ubuntu SMP Wed Oct 11 18:35:14 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
jon@ubuntu:~$ sudo --version
Sudo version 1.8.20p2
Sudoers policy plugin version 1.8.20p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.20p2
linux bash signals sudo kill
2个回答
1
投票

对于任何给定信号的信号屏蔽位为:

(1ULL << ((signal_number) - 1))

(对于在1-32范围内的标准信号无论如何;附加信号在“实时”信号集和稍微不同的方式处理,尽管相同的概念内)。所以CAUGHT面具的有趣的部分是:

...7a07

其是(+为抓住, - 对于没有被捕获,在扩张部分):

xxx7: signals 1, 2, 3, but not 4: +SIGHUP  +SIGINT  +SIGQUIT -SIGILL
xx0x: not 5-8:                    -SIGTRAP -SIGABRT -SIGBUS  -SIGFPE
xaxx: not 9, 10, not 11, 12:      -SIGKILL +SIGUSR1 -SIGSEGV +SIGUSR2
7xxx: 13, 14, 15, not 16:         +SIGPIPE +SIGALRM +SIGTERM -SIGSTKFLT

(可以继续,如果你喜欢解码其余;参见/usr/include/asm-generic/signal.h为Linux特定的信号数;注意该数值定义在OSX上不同,并且BSD但该技术是相同的:卡住或堵塞或任何信号被表示为1比特在掩模)。

因此,这意味着sudo正赶上SIGTERM但不要再追SIGABRT。该SIGTERM未传递的事实必须有事情做与sudo代码本身。源(apt-get source sudo)有做信号处理,包括一些有趣的调试技巧,你可以打开在sudo的配置文件,以帮助您跟踪这是怎么回事了一些相当复杂的代码。


0
投票

我发现下面的须藤的源代码注释

  /*  
 * 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.
 */
© www.soinside.com 2019 - 2024. All rights reserved.