web-dev-qa-db-ja.com

複数の並列wgetを生成して保存すると、すべてのwgetが完了したときにbash配列がきれいに出力されます。

自分のWebサイトに、キャリッジリターンで区切られたテキストファイルにリストされているURLの長いリストがあります。たとえば、次のようになります。

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

各URLを2回ヒットし、特定のヘッダーを確認して取得し、結果を配列に保存して、Niceレポートに出力するには、多数の並列wgetを生成する必要があります。

次のxargsコマンドを使用して、必要なものの一部を取得します。

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

問題は、このコマンドを2回実行して、以下を保存する方法です。

  1. ヒットしたURL
  2. Cachingヘッダーに対するgrepの最初の結果
  3. Cachingヘッダーに対するgrepの2番目の結果

したがって、出力は次のようになります。

=====================================================
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の達人は、私がどのように進めるかについて何か提案がありますか?

5
Brad

(terdonのコードに基づいて)単一のURLを指定して正しいことを行う小さなスクリプトを作成します。

#!/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は、2つのプロセスからの出力が混合されないようにします-xargsが提供しない保証。

GNU Parallel at: http://www.gnu.org/s/parallel/

GNU Parallelをわずか10秒でインストールできます:

wget -O - pi.dk/3 | sh 

http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1 の紹介ビデオをご覧ください

3
Ole Tange

指定したコマンドは\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がある場合、これを並行して実行する理由は確かに理解できます。試すことができることの1つは、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 )

そこで起動される2つのサブシェルがあり、最初の(while ... < urls.txt)完了メッセージの抑制 にあります。 2番目(( echo "=== ... ) > mktemp urltmpXXX)は、特定のURLのすべての出力を1つのファイルに収集するためのものです。

上記のスクリプトは、urltmpXXXと呼ばれる22,000のtmpファイルを作成します。ここで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

もう1つの問題は、これにより22000個のジョブが一度に起動されることです。システムによっては、これが問題になる場合と問題にならない場合があります。これを回避する1つの方法は、入力ファイルをsplitしてから、ファイルごとに上記のループを1回実行することです。

0
terdon

簡単な解決策の1つは、各wgetコマンドからの出力を個別のファイルに記録し、後でcatを使用してそれらをマージすることです。

0
l0b0