10

先介绍一点背景 - 当我apt-get install从公司互联网下载时,它会在前 10 秒左右提供高速爆发(400-500KB/s),然后下降到该速度的十分之一(40-50KB/s),然后几分钟后到了一个真正的惨(4-5KB/s)。这让我觉得系统管理员已经实施了某种网络节流方案。

现在我知道网络不仅仅是不稳定的,因为如果我启动一个apt-get install fooCtrl-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

这似乎有效。它生成 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. 如果 SIGINT 来自脚本而不是交互式 shell,则 Apt-get 处理 SIGINT 的方式不同。再一次,上面的“实验”证明这不是真的。

4

3 回答 3

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`

所以我相信sudo捕捉到信号并将其他东西(sigterm?sighup?)发送到apt-get.

于 2011-07-08T12:51:20.653 回答
5

好的谜团解开了!感谢印度 Linux 用户组的乐于助人的人们。

这里的答案有两个——

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

[~] ➔ file /usr/lib/apt/methods/http

/usr/lib/apt/methods/http: ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15,
stripped

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

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

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

#!/bin/sh
for i in `seq 1 100` ; do
    sudo apt-get install foo -y &
    sleep 10
    sudo kill -2 `ps -ae | grep " http" | awk '{print $1}'`
done
于 2011-08-05T13:09:49.557 回答
0

好吧,正如cnicutar所说,它只是发送一个 SIGINT。现在,所说的关键在这里:

我怀疑信号没有发送到 apt-get

这是真的。让我解释。

运行sudo foo启动一个sudo进程,然后(即在您插入密码之后)调用foo;这是论点。一旦sudo接受密码并调用foo您进入foo空间”。无论您在等待foo完成时所做的一切都是基于foo而不是 sudo。

因此,发送一段CtrlC时间等待apt完成其工作,该信号被发送到apt.

现在,如果你 start sudo,它的pid存储在$!var 中。kill向该 pid/var 发送信号是向 发送信号killsudo而不是apt后来由 sudo 启动的信号。如果您想向您发送kill信号,apt您可能需要使用pidof实用程序。

自己测试:

sudo do-something
echo $!
pidof do-something

输出应该是两个不同的pid
我希望这会有所帮助。

于 2011-07-08T16:26:35.280 回答