自分のWebサイトに、キャリッジリターンで区切られたテキストファイルにリストされているURLの長いリストがあります。たとえば、次のようになります。
各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回実行して、以下を保存する方法です。
したがって、出力は次のようになります。
=====================================================
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の達人は、私がどのように進めるかについて何か提案がありますか?
(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 の紹介ビデオをご覧ください
指定したコマンドは\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回実行することです。
簡単な解決策の1つは、各wget
コマンドからの出力を個別のファイルに記録し、後でcat
を使用してそれらをマージすることです。