生成多个并行 wget,并将结果存储在 bash 数组中,以便在所有 wget 完成后以漂亮的方式打印出来

生成多个并行 wget,并将结果存储在 bash 数组中,以便在所有 wget 完成后以漂亮的方式打印出来

我在自己的网站上有一个很长的 URL 列表,以回车符分隔的文本文件形式列出。例如:

  • http://www.mysite.com/url1.html
  • http://www.mysite.com/url2.html
  • http://www.mysite.com/url3.html

我需要生成多个并行的 wget 来两次访问每个 URL,检查并检索特定的标头,然后将结果保存在一个数组中,以便输出为一份漂亮的报告。

我使用以下 xargs 命令获得了我想要的部分内容:

xargs -x -P 20 -n 1 wget --server-response -q -O - --delete-after<./urls.txt 2>&1 | grep Caching

问题是如何运行此命令两次并存储以下内容:

  1. URL 命中
  2. 针对缓存标头执行 grep 的第一个结果
  3. 针对缓存标头执行 grep 的第二个结果

因此输出应类似于:

=====================================================
http:/www.mysite.com/url1.html
=====================================================
First Hit: Caching: MISS
Second Hit: Caching: HIT

=====================================================
http:/www.mysite.com/url2.html
=====================================================
First Hit: Caching: MISS
Second Hit: Caching: HIT

等等。

只要标头与 URL 关联,URL 出现的顺序就不一定是个问题。

由于 URL 数量较多,我需要并行访问多个 URL,而不是连续访问,否则会花费太长时间。

诀窍在于如何获取多个并行 wget 并以有意义的方式存储结果。如果有更合乎逻辑的方法(例如写入日志文件?),我不会坚持使用数组。

有没有 bash 专家对我该如何进行有什么建议?

答案1

制作一个小脚本,根据一个 url 执行正确的操作(基于 terdon 的代码):

#!/bin/bash

url=$1
echo "=======================================";
echo "$url"
echo "=======================================";
echo -n "First Hit: Caching: ";
wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
if [ $? == 0 ]; then echo HIT; else echo MISS; fi;
echo -n "Second Hit: Caching: ";      
wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
if [ $? == 0 ]; then echo HIT; else echo MISS; fi; echo "";

然后使用 GNU Parallel 并行运行此脚本(例如,一次 500 个作业):

cat urls.txt | parallel -j500 my_script

GNU Parallel 将确保两个进程的输出永远不会混合 - xargs 无法提供这样的保证。

您可以在以下位置找到有关 GNU Parallel 的更多信息:http://www.gnu.org/s/parallel/

您只需 10 秒即可安装 GNU Parallel:

wget -O - pi.dk/3 | sh 

观看简介视频http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

答案2

一个简单的解决方案是将每个命令的输出记录wget到单独的文件中,cat然后用于合并它们。

答案3

我会假设您的文件是换行符,而不是回车符分隔的,因为您给出的命令不适用于\r分隔文件。

如果您的文件使用\r而不是\n作为行尾,\n通过运行以下命令将其更改为使用:

perl -i -pe 's/\r/\n/g' urls.txt 

如果你使用 Windows 风格 ( \r\n) 的行尾,请使用以下命令:

perl -i -pe 's/\r//g' urls.txt 

现在,一旦你有 Unix 格式的文件,如果你不介意你的工作不能并行运行,你可以这样做:

while read url; do 
  echo "=======================================";
  echo "$url"
  echo "=======================================";
  echo -n "First Hit: Caching: ";
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi;
  echo -n "Second Hit: Caching: ";      
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi; echo "";
done < urls.txt

更新以回应您的评论:

如果你有 22,000 个 URL,我确实可以理解你为什么要并行执行此操作。你可以尝试创建 tmp 文件:

(while read url; do 
 ( 
  echo "=======================================";
  echo "$url"
  echo "=======================================";
  echo -n "First Hit: Caching: ";
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi;
  echo -n "Second Hit: Caching: ";      
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi; 
  echo ""; ) > `mktemp urltmpXXX` 2>/dev/null&
done < urls.txt )

有两个子外壳被启动在那里,第一个(while ... < urls.txt)只是用来禁止显示完成消息. 第二个 ( ( echo "=== ... ) > mktemp urltmpXXX) 用于将给定 URL 的所有输出收集到一个文件中。

上述脚本将创建 22,000 个 tmp 文件,urltmpXXX其中 被XXX替换为尽可能多的随机字符。由于 tmp 文件在全部完成后将分别包含 6 行文本,因此您可以使用以下命令监视(并可选择删除文件):

b=`awk 'END{print NR}' urls.txt`; 
while true; do 
 a=`wc -l urltmp* | grep total | awk '{print $1}'`;     
 if [ $a == $((6 * $b)) ]; then cat urltmp* > urls.out; break; 
  else sleep 1; fi; 
done

现在另一个问题是,这将同时启动 22000 个作业。根据您的系统,这可能是也可能不是问题。解决此问题的一种方法是split输入文件,然后对每个文件运行一次上述循环。

相关内容