技術メモ帳 このページをアンテナに追加 RSSフィード

2007-01-17

[]xargsコマンドを使って指定したコマンドを並列実行させる 22:18 xargsコマンドを使って指定したコマンドを並列実行させるを含むブックマーク xargsコマンドを使って指定したコマンドを並列実行させるのブックマークコメント

あまり知られていないが、GNUのxargsコマンドには、

プロセスの最大数を設定できるオプションというのが用意されている。

コレを使って、プロセスを並列実行させてみよう。

xargs --max-procs=MAX-PROCS -P MAX-PROCS command

MAX-PROCSに数字を指定すると、

最大で、その数だけ command プロセスを生成する。

デフォルトは、1プロセスだけになっている。


いくつか例を交えて説明する。

サンプルとして、以下のようにURLが行ごとに記述されたファイルを元に

curlをxargsで並列実行して、HTMLデータを取得してみよう。

$ cat ./url_list.txt
http://www.google.co.jp/
http://www.yahoo.co.jp/
http://b.hatena.ne.jp/

まず、普通にxargsを使ってcurlを実行した場合だ。

xargs -n1 command とすることで、

標準入力の1つの要素(改行またはスペースで区切られた)を

引数に 要素数分 command を実行できる。

もちろんこれはxargsの基本だ。

$ cat url_list.txt | xargs -n1 curl >/dev/null
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100  2824    0  2824    0     0  19210      0 --:--:--  0:00:00 --:--:-- 1680k
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 67470    0 67470    0     0   383k      0 --:--:--  0:00:00 --:--:-- 1139k
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 59199  100 59199    0     0  32961      0  0:00:01  0:00:01  0:00:00 84570

/dev/null デバイスに標準出力のデータをリダイレクトしているのは、

curlが標準出力に、取得したHTMLデータを出力してくれるのだが

今回は特に使わないからだ。


しかし、この出力では現在どのURLを取得する処理が行われているのかが

非常にわかりにくい。工夫してみよう。

-t オプションで、xargsが実行しようとするコマンドが表示できる。

$ cat url_list.txt | xargs -t -n1 curl >/dev/null 
curl http://www.google.co.jp/ 
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100  2824    0  2824    0     0  19081      0 --:--:--  0:00:00 --:--:-- 1680k
curl http://www.yahoo.co.jp/ 
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 69963    0 69963    0     0   276k      0 --:--:--  0:00:00 --:--:--  601k
curl http://b.hatena.ne.jp/ 
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 59247  100 59247    0     0  56913      0  0:00:01  0:00:01  0:00:00  755k

さて、ココからが本題である。

冒頭で説明した通り、-P オプションを利用すると並列実行させる事が可能である。

-P3 と指定する事で、3プロセスで並列実行してみる。

$ cat url_list.txt | xargs -P3 -t -n1 curl >/dev/null 
curl http://www.google.co.jp/ 
curl http://www.yahoo.co.jp/ 
curl http://b.hatena.ne.jp/ 
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100   988    0   988    0     0   3207      0 --:--:--  0:00:00 --:--:--  320  7% Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100  2824    0  2824    0     0   7736      0 --:--:--  0:00:00 --:--:--     0
100 69963    0 69963    0     0   164k      0 --:--:--  0:00:00 --:--:--  623k
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 59253  100 59253    0     0  40089      0  0:00:01  0:00:01  0:00:00  263k

最初に、3つのコマンドが実行されており、

その出力結果がカオス(ごちゃまぜ)になってる。

標準エラー出力は行バッファリングされていないからだ。

なんとなく並列実行されてるのがわかるだろうか。


わざわざ最大プロセス数を指定するのは面倒だ。

そんなときは、 -P0 と指定する事で、

可能な限りプロセスを生成してくれるようになる。

今回は、要素が3つ(URL)なので、3プロセスで実行してくれる。

$ cat url_list.txt | xargs -P0 -t -n1 curl >/dev/null 
curl http://www.google.co.jp/ 
curl http://www.yahoo.co.jp/ 
curl http://b.hatena.ne.jp/ 
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 69963    0 69963    0     0   156k      0 --:--:--  0:00:00 --:--:--  609k
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100  2824    0  2824    0     0   5822      0 --:--:--  0:00:00 --:--:-- 1680k
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 59261  100 59261    0     0  65699      0  0:00:00  0:00:00  0:00:00  845k

僕の感じるメリットは、既存のプログラムをこれほどまで簡単に

"コマンドの連鎖" のなかで並列化する事が可能であるということ。

つまり、アナタはシングルプロセスで(しっかりと)動くプログラムさえ作れば

xargsを使って気軽に並列化する事が出来る、という事だ。


--

ここからはギーク向け。

POSIXでは、この -P は定義されてない。


Reference - POSIX xargs

http://www.opengroup.org/onlinepubs/009695399/utilities/xargs.html


そんなわけで、移植性が高い方法をお望みならば

先日書いた、zargsを利用するという方法もある。

zshのzargsコマンドの使い方 - 技術メモ帳


zshが無ければ動かないが、zshがあれば動くという前提にする事が出来るのだ。

ただ残念ながら、zargsのマニュアルにも書いてあるが

xargsとオプションは完全に互換だが、標準入力からは読み込まない点が違う。

というわけで、バッククォート演算子などを利用してURLリストを読み込んでいる。

% autoload zargs
% zargs -P0 -t -n1 -- $(cat ./url_list.txt) -- curl >/dev/null 
curl http://www.google.co.jp/
curl http://www.yahoo.co.jp/
curl http://b.hatena.ne.jp/
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100   988    0   988    0     0   3058      0 --:--:--  0:00:00 --:--:--  3058  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100  2824    0  2824    0     0   8022      0 --:--:--  0:00:00 --:--:-- 1680k
100 69528    0 69528    0     0   150k      0 --:--:--  0:00:00 --:--:--  522k
  % Total    % Received % Xferd  Average Speed          Time             Curr.
                                 Dload  Upload Total    Current  Left    Speed
100 59548  100 59548    0     0  29968      0  0:00:01  0:00:01  0:00:00 86301

文章が長くなってしまった。

世の中というものは、くだらないものほど冗長である。

おそらく、そのように世界が出来ているのか、あるいは、

人間がそのように感じるように遺伝子で定義されているかであろう。

$ wget -O - -i ./url_list.txt 

参考文献:

http://www.linux.or.jp/JM/html/GNU_findutils/man1/xargs.1.html

ななしななし 2007/01/17 22:22 userContent.cssで消えますよ。
@-moz-document domain(”reader.livedoor.com”) {
.adfeeds_body { display: none !important; }
}

lurkerlurker 2007/01/17 22:33 なるほど確かにその通りです。素敵です。

hogehoge 2007/01/18 10:54 最後の wget ステートメントがヲチとしていい味出てますね

lurkerlurker 2007/01/18 21:16 hogeさんはすばらしい感性をお持ちなのでしょうか。
僕と通じるものがありますね。