当您执行Ctrl-C时,BASH会发生什么(提示,它不仅仅是发送SIGINT)

Anu*_*ain 9 bash apt kill process sigint

首先有一点背景 - 当我apt-get install从我公司的互联网上下载时,它会在前10秒左右提供高速(400-500KB/s),然后下降到十分之一(40-50KB/s),然后几分钟后真正悲惨(4-5KB/s).这让我觉得系统管理员已经实现了某种网络限制方案.

现在我知道网络不是简单的不稳定,因为如果我开始apt-get install foo,Ctrl-C它会在10秒后立即apt-get install foo再次运行(通过向上箭头并输入以使用bash历史记录),然后继续重复此过程几分钟直到所有包都下载了,我甚至可以非常快速地下载大包.特别是,即使在使用Ctrl-C中止下载后,apt-get似乎也能够在下次调用时恢复下载.

当然,盯着屏幕每隔10秒做一次Ctrl-C Up Enter真的很快,所以我写了一个shell脚本 -

#!/bin/sh
for i in `seq 1 100` ; do
    sudo apt-get install foo -y &
    sleep 10
    sudo kill -2 $!
done
Run Code Online (Sandbox Code Playgroud)

这似乎有效.它产生apt-get,运行10秒然后杀死(通过发送SIGINT)并再次启动它.但是,它并没有真正起作用,因为现在apt-get不会在后续调用中恢复下载!

sudo apt-get install foo从一个终端运行然后kill -2 <PID of apt-get>从另一个终端运行的实验.即使在这种情况下,当我重新启动apt-get时,它也不会恢复下载.

很明显,Ctrl-C 等同于SIGINT.当我手动执行Ctrl-C时会发生其他事情,这会让apt-get有机会保存下载状态.问题是 - 它是什么?

编辑

这些是我到目前为止收到的建议,但没有雪茄.神秘加深了! -

  1. sudo kill -2 $!该信号可能会sudo代替apt-get.这不是原因,因为如上所述我也尝试将SIGINT专门发送到apt-get的PID,甚至阻止apt-get保存其状态.

  2. Sudo捕获信号并向apt-get发送一些其他信号.我试着发送apt-get所有我能想到的信号!它仍然没有恢复其中任何一个的下载.它只在我执行Ctrl-C杀死它时才恢复下载.

  3. 如果来自脚本而不是交互式shell,则Apt-get处理SIGINT的方式不同.再次,上面的"实验"证明这不是真的.

cni*_*tar 5

提示,它不仅仅是发送SIGINT).

是的它只是发送SIGINT:-)节流是正在发生的事情,你已经做到了.这是我怀疑发生的事情:

  • 有些东西限制了连接的带宽.为了跟踪连接,它还包括源端口(这是一个坏主意IMO)和其他参数

  • 当你杀掉apt-get并重新启动它时,它自然会获得一个新的TCP源端口,并且你会想到的邪恶实体限制," 哦,这是一个新的连接 ",它实际上是

那么你如何加快速度呢?那么真正的解决方案是使用多个并行下载.我自己从未使用它,但我听说过一个名为"apt-fast"的工具(实际上是一个bash脚本本身),它做了类似的事情.

编辑

在再次阅读问题后,我怀疑信号没有被发送到apt-get.

sudo apt-get install foo -y &
sudo kill -2 $! # sends signal to sudo, which sends whatever it wants to `apt-get`
Run Code Online (Sandbox Code Playgroud)

所以我相信sudo捕获信号并发送其他信息(sigterm?sighup?)apt-get.


Anu*_*ain 5

好吧谜团解开了!感谢印度 Linux 用户组的热心人士。

\n\n

这里的答案有两个方面——

\n\n

首先,apt-get调用另一个程序来http下载数据。

\n\n
[~] \xe2\x9e\x94 file /usr/lib/apt/methods/http\n\n/usr/lib/apt/methods/http: ELF 32-bit LSB executable, Intel 80386, version 1\n(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15,\nstripped\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,这是一个可执行文件,甚至不是脚本,可能是为了在系统安装期间支持在 perl/python/ruby 等尚不可用时下载文件。

\n\n

其次,当您在运行后按 Ctrl-C 时apt-get,SIGINT 将发送到http,而不是发送到apt-get。当http收到SIGINT时,它会保存关闭前的下载状态。

\n\n

这是完美运行的更新脚本 -

\n\n
#!/bin/sh\nfor i in `seq 1 100` ; do\n    sudo apt-get install foo -y &\n    sleep 10\n    sudo kill -2 `ps -ae | grep " http" | awk \'{print $1}\'`\ndone\n
Run Code Online (Sandbox Code Playgroud)\n