【问题标题】:Parallel wget in Bash [duplicate]Bash中的并行wget [重复]
【发布时间】:2011-11-26 12:24:04
【问题描述】:

我从一个网站获得了一堆相对较小的页面,我想知道我是否可以在 Bash 中以某种方式并行执行。目前我的代码看起来像这样,但执行需要一段时间(我认为让我慢下来的是连接的延迟)。

for i in {1..42}
do
    wget "https://www.example.com/page$i.html"
done

我听说过使用 xargs,但我对此一无所知,而且手册页非常混乱。有任何想法吗?甚至可以并行执行此操作吗?有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: bash parallel-processing wget


    【解决方案1】:

    在命令中添加与号使其在后台运行

    for i in {1..42}
    do
        wget "https://www.example.com/page$i.html" &
    done
    

    【讨论】:

      【解决方案2】:

      您可以使用-b 选项:

      wget -b "https://www.example.com/page$i.html"
      

      如果您不想要日志文件,请添加选项-o /dev/null

      -o FILE 将消息记录到 FILE。

      【讨论】:

      • 不,没关系 - 检查手册页('-o logfile...')。
      • 对不起,我没有正确阅读。我以为您说“如果您不想要输出文件,请添加选项 -o”。因为我这样做了,最终在 /root 中得到了数十万个文件。感谢您的澄清。
      【解决方案3】:

      仅在后台运行作业并不是一个可扩展的解决方案:如果您要获取 10000 个 url,您可能只想并行获取几个(比如 100 个)。 GNU Parallel 就是为此而生的:

      seq 10000 | parallel -j100 wget https://www.example.com/page{}.html
      

      更多示例请参见手册页: http://www.gnu.org/software/parallel/man.html#example__download_10_images_for_each_of_the_past_30_days

      【讨论】:

      • 抱歉,我现在没有可下载的内容,但我肯定会在以后下载。假设我运行 seq 30 | parallel -j5 mkdir /tmp/{} 是否应该创建 30 个文件夹 /tmp/1 /tmp/2 等?如果是这样,它不会在我的系统上执行此操作。
      • @ka3ak 你可能发现了一个错误。请关注:gnu.org/software/parallel/man.html#REPORTING-BUGS
      • @OleTange 我的系统上似乎预装了另一个同名工具。它甚至可以选择 -j 用于工作。我刚刚运行 sudo apt install parallel 来安装正确的。
      【解决方案4】:

      比使用&-bwget 推到后台更可取,您可以使用xargs 达到相同的效果,而且效果更好。

      优点是xargs正确同步,无需额外工作。这意味着您可以安全地访问下载的文件(假设没有发生错误)。一旦xargs 退出,所有下载都将完成(或失败),您可以通过退出代码知道一切是否顺利。这比忙着等待sleep 和手动测试完成要好得多。

      假设 URL_LIST 是一个包含所有 URL 的变量(可以在 OP 的示例中使用循环构造,但也可以是手动生成的列表),运行以下代码:

      echo $URL_LIST | xargs -n 1 -P 8 wget -q
      

      一次将一个参数(-n 1)传递给wget,并且一次最多执行8个并行wget进程(-P 8)。 xarg 在最后一个生成的进程完成后返回,这正是我们想知道的。不需要额外的诡计。

      我选择的 8 个并行下载的“神奇数字”并不是一成不变的,但这可能是一个很好的折衷方案。 “最大化”一系列下载有两个因素:

      一个是填充“电缆”,即利用可用带宽。假设“正常”条件(服务器比客户端拥有更多带宽),这已经是一次或最多两次下载的情况。在问题上抛出更多连接只会导致数据包被丢弃和 TCP 拥塞控制启动,并且 N 次下载,每个渐近 1/N 带宽,达到相同的净效果(减去丢弃的数据包,减去窗口大小恢复)。丢包在 IP 网络中是很正常的事情,拥塞控制就是这样工作的(即使是单个连接),通常影响几乎为零。然而,拥有不合理的大量连接会放大这种效果,因此它可能会变得很明显。无论如何,它不会使任何事情变得更快。

      第二个因素是连接建立和请求处理。在这里,在飞行中拥有一些额外的连接真的很有帮助。面临的问题是两次往返的延迟(通常在同一地理区域内为 20-40 毫秒,洲际为 200-300 毫秒)加上服务器实际处理请求和推送回复所需的奇数 1-2 毫秒到插座。这并不是很多时间本身,但乘以几十/万个请求,它很快就会加起来。
      有六到十个请求在进行中会隐藏大部分或全部延迟(它仍然存在,但由于它重叠,所以不能总结!)。同时,只有少数并发连接不会产生不利影响,例如导致过度拥塞或强制服务器分叉新进程。

      【讨论】:

      • 这绝对是最好的方法,因为它使用了通用工具xargs,而且这种方法可以应用于许多其他命令。
      • 当通过 HTTP 下载多个文件时,由于 Keep-Alive 机制,wget 可以重用 HTTP 连接。当您为每个文件启动一个新进程时,无法使用此机制,并且必须一次又一次地建立连接(TCP 三重握手)。所以我建议将 -n 参数提高到大约 20 左右。在默认配置中,Apache HTTP 服务器在一个保持活动会话中最多只能处理 100 个请求,因此这里可能没有意义。
      • 很好的答案,但是如果我想将两个变量值传递给 wget 怎么办?我想指定目标路径以及 URL。使用 xargs 技术仍然可以做到这一点吗?
      • @DomainsFeatured xargs 没有选项可以做到这一点。这也是最初开发 GNU Parallel 的原因之一。
      • @Justin 您可以只使用cat ./urls | xargs -n 1 -P 8 wget [...],甚至更好的xargs -a ./urls -n 1 -P 8 wget [...],而不是将文件读入变量。
      【解决方案5】:

      wget 版本 2 实现多个连接。

      https://github.com/rockdaboot/wget2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多