我试图找出为什么这不起作用:
#!/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
过程遭到停权?
我想出了几种解决方法(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
对于任何给定信号的信号屏蔽位为:
(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的配置文件,以帮助您跟踪这是怎么回事了一些相当复杂的代码。
我发现下面的须藤的源代码注释
/*
* 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.
*/