当我sleep
手动运行,然后kill -INT
它,睡眠立即退出。例如:
$ /bin/sleep 60 &
[1] 4002356
$ kill -INT 4002356
[1]+ Interrupt /bin/sleep 60
$ ps -C sleep
PID TTY TIME CMD
$
Run Code Online (Sandbox Code Playgroud)
但是,当我在 shell 脚本中做同样的事情时,会sleep
忽略SIGINT
. 例如:
set -o xtrace
echo
/bin/sleep 10 &
child="$!"
/bin/sleep 0.1
ps -C sleep
kill -TERM "$child" # SIGTERM
/bin/sleep 0.1
ps -C sleep
wait "$child" # will return immediately
echo
/bin/sleep 10 &
child="$!"
/bin/sleep 0.1
ps -C sleep
kill -INT "$child" # …
Run Code Online (Sandbox Code Playgroud) 我不明智地要求gdb
列出所有定义的函数。
(gdb) info function
Run Code Online (Sandbox Code Playgroud)
现在它正在兴奋地占用 CPU 和内存。如果我真的很快,GDB 将停止使用 Ctrl-C 并再次提示我。
(gdb) info functions
^CQuit
(gdb)
Run Code Online (Sandbox Code Playgroud)
但是如果我太慢,它就不会响应 Ctrl-C (SIGINT)、Ctrl-\ (SIGQUIT) 或 SIGTERM。
(gdb) info functions
^C^C^\
Run Code Online (Sandbox Code Playgroud)
奇怪的是,GDB 确实响应了 SIGUSR1。
(gdb) info functions
^C^C^\User defined signal 1
Run Code Online (Sandbox Code Playgroud)
但是,这结束了我的 GDB 会话,我必须重新开始。是否有另一种方法可以停止不会完全杀死 GDB 的缓慢运行的命令?
作为记录,我在 Debian 9.3 (stretch) 上运行 GDB 版本 7.12.0.20161007-git。
我继承了旧电脑,服务器(四奔腾4)只有分区的/
,/boot
和swap
(RAID1 2个1T SATA磁盘),但更新(从CentOS的6.9)的发行需要。我决定创建一个新分区,以便/
可以格式化包含的分区。
但是我忘记添加-p
标志resize2fs
,现在它默默地盯着我看,我不知道它需要多长时间(它已经持续了 50 多个小时)。现在,我知道缩小文件系统可能需要很长时间,但是虽然我可以等待100 小时,但800 小时之类的时间是不可能的。
这是我目前的想法:
Ctrl
+ C
&& e2fsck
。resize2fs -p ...
但我一直没能找到共识上是多么危险的是送SIGINT到resize2fs
。
我确实有重要信息的额外备份,但仍然希望在不损坏文件系统的情况下执行此操作。是的,我知道从头开始安装发行版并恢复备份可能会更快。
更新:我决定打断它。一切似乎都很好,但问题仍然存在。我还是很好奇。
我想进行特定的键盘键组合以终止进程,例如我想通过按 CTRL + C ^ 3(按三下 C:CTRL + CCC)来终止进程。
所以基本上我想用 CTRL + CCC 替换 CTRL + C
我们知道,除了SIGKILL
和之外SIGSTOP
,程序还可以拦截 IPC 信号,并运行其内部处理程序来绕过默认处理程序的操作。
我至少能想到一个利用SIGINT
信号执行此操作的充分理由。
我还可以想到恶意软件可能捕获并阻止 SIGINT 的一个很好的理由:
即延长进程的执行时间。对于大多数用户来说,Ctrl+C是大多数终端用户的键盘快捷键,有很多人不知道Ctrl+ Z(SIGTSTP
它只会停止进程,保留在终端中jobs
),更不用说Ctrl+了\,它发送SIGQUIT
并创建一个核心转储。
如果Ctrl+C被捕获并被阻止,此类用户可能会尝试打开另一个终端窗口,并运行以下内容:
ps aux | grep [process name]
Run Code Online (Sandbox Code Playgroud)
获取进程PID,并执行SIGKILL
kill -9 [$PID]
Run Code Online (Sandbox Code Playgroud)同样,连接到远程计算机上的终端会话的用户将尝试与新的终端会话建立第二个连接,并通过类似的进程/PID 搜索来终止罪魁祸首。显然,这种策略可能只会延长进程运行时间很短一段时间,但即使使用 10MB/s 高带宽连接的文件传输过程额外 3 分钟,也会传输近 2 GB 的额外数据,因此肯定有一些优点它。
然而,最近我注意到——也许只是因为我开始关注它——有些程序似乎属于另一个子集。
这些程序是开源的,并且对软件包进行了足够的维护和检查,隐藏主要的恶意软件代码似乎不太可能。
vim
它们不像其他文本编辑器那样控制键盘输入
他们有内部处理程序来捕获 SIGINT 并完全忽略它。没有最终的进程终止,并且据所知,没有尝试最后的关键任务。
我的问题:
进程出于合法目的可能选择拦截但完全丢弃 SIGINT 是否有可能的原因?
换句话说,是否有充分的理由(从代码或系统的角度来看)或情况,捕获并忽略 SIGINT 比其已知的默认操作(终止正在运行的进程)更有利?
我正在尝试将 SIGINT 信号发送到多个进程,我认为这是正确的:
kill -2 <pid1> <pid2> ... <pid3>
Run Code Online (Sandbox Code Playgroud)
但我无法确认...
我知道,由于这个问题esc,如果我按然后输入:q!
,我可以退出编辑器。vim
但是,标准约定是当按下ctrl+时程序退出,这会将 a 发送到当前正在运行的进程。cSIGINT
例如,top
、tail -f
和ping
都遵循此约定。
我的问题是:为什么不vim
遵循这个既定的惯例?是有历史原因,还是另有原因?
在我看来,如果它像其他所有事情一样遵循这个标准约定,将会避免新用户的很多困惑。
(当我们这样做时,为什么会这样SIGINT
而不是SIGTERM
首先呢?)