【问题标题】:sudo ignores SIGTERM sent from same scriptsudo 忽略从同一脚本发送的 SIGTERM
【发布时间】:2017-12-29 22:27:26
【问题描述】:

我试图弄清楚为什么这不起作用:

#!/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 进程,我认为这很重要。也可以在 so.sh 脚本仍在运行时从不同的 shell 成功终止 sudo sleep 60 进程。

我还注意到在脚本中使用sudo kill -ABRT(而不是kill 的默认SIGTERM)确实成功杀死了sudo 进程,所以我认为这与@ 的方式有关987654339@ 处理 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 进程没有被终止?

我想出了几种解决方法(setsid、sudo -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


    【解决方案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 配置文件中打开以帮助您跟踪发生了什么。

    【讨论】:

    • 感谢您提供有关信号的更多信息! sudo 捕获 SIGTERM 是有道理的,因为当它源自 sudo 的子进程时,它不会传播该信号。如果我真的想知道,我想我必须深入研究源代码(感谢那个 apt 指针)。
    【解决方案2】:

    我在 sudo 的源代码中发现了以下 cmets

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

    【讨论】:

    • 嘿!非常感谢您的回复。文档中明显缺少这一点。
    【解决方案3】:

    如果您将sudo kill $sudo_pid 更改为setsid sudo kill $sudo_pid,它将起作用。

    在这里找到这个:starting a new process group from bash script

    【讨论】:

      猜你喜欢
      • 2016-08-12
      • 2013-06-24
      • 2010-09-09
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      • 2011-07-18
      • 1970-01-01
      • 2018-03-05
      相关资源
      最近更新 更多