twitter で一瞬話題になってたのを見かけたのでちょっとだけ使ってみた。
が perl だったのでげんなり。 xargs -P と比べれば早くはないけど、 pcntl_fork() なんかに比べればだいぶ早い。
% time seq 1000 | xargs -P4 -I{} echo {} >/dev/null seq 1000 0.00s user 0.00s system 0% cpu 0.003 total xargs -P4 -I{} echo {} > /dev/null 0.12s user 0.39s system 268% cpu 0.191 total
% time seq 1000 | parallel -P4 -I{} echo {} >/dev/null seq 1000 0.00s user 0.00s system 0% cpu 0.003 total parallel -P4 -I{} echo {} > /dev/null 1.24s user 1.60s system 150% cpu 1.882 total
試行錯誤した限りだと、 {} がないと arg に必ず入っちゃうのかな?
% seq 3 | xargs -I{} sh -c 'set -x; ps h -p $$ -o pid,pgid' + ps h -p 4056 -o pid,pgid 4056 4054 + ps h -p 4058 -o pid,pgid 4058 4054 + ps h -p 4060 -o pid,pgid 4060 4054
% seq 3 | parallel -I{} 'set -x; ps h -p $$ -o pid,pgid' + ps h -p 4193 -o pid,pgid 1 1 1 4193 4153 + ps h -p 4194 -o pid,pgid 2 2 0 4194 4153 + ps h -p 4196 -o pid,pgid 3 3 0 4196 4153
ファイル名を便利に扱うための置換マーカみたいなのが最初から入ってる。 {} = aho/baka.dat だとして
- {.} = aho/baka
- {/} = baka.dat
- {/.} = baka
となる。 paralles ssh 的に使うと便利、みたいな例が幾つか上がってて、たしかに DNS 的ホスト名もファイル名も "." で区切るよな、と思った。
なんでちょっといじった。いや、ほら、だいたい 3 つ削ればホスト名になるじゃん。
-- ./opt/src/parallel/parallel-20110322/src/parallel 2011-03-22 09:00:52.000000000 +0900 +++ /home/ichii386/opt/bin/parallel 2011-04-25 21:06:51.000000000 +0900 @@ -391,8 +391,12 @@ $Global::quoting = 0; $Global::replace{'{}'} = '{}'; $Global::replace{'{.}'} = '{.}'; + $Global::replace{'{..}'} = '{..}'; + $Global::replace{'{...}'} = '{...}'; $Global::replace{'{/}'} = '{/}'; $Global::replace{'{/.}'} = '{/.}'; + $Global::replace{'{/..}'} = '{/..}'; + $Global::replace{'{/...}'} = '{/...}'; $/="\n"; $Global::ignore_empty = 0; $Global::interactive = 0; @@ -3092,7 +3096,11 @@ '{}' => 0, # Total length of all {} replaced with all args '{/}' => 0, # Total length of all {/} replaced with all args '{.}' => 0, # Total length of all {.} replaced with all args + '{..}' => 0, # Total length of all {..} replaced with all args + '{...}' => 0, # Total length of all {...} replaced with all args '{/.}' => 0, # Total length of all {/.} replaced with all args + '{/..}' => 0, # Total length of all {/..} replaced with all args + '{/...}' => 0, # Total length of all {/...} replaced with all args 'no_args' => undef, # Length of command with all replacement args removed 'context' => undef, # Length of context of an additional arg }; @@ -3903,11 +3911,27 @@ # skip } elsif($replacement_string eq "{.}") { $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + } elsif($replacement_string eq "{..}") { + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + } elsif($replacement_string eq "{...}") { + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument } elsif($replacement_string eq "{/}") { $s =~ s:^.*/([^/]+)/?$:$1:; # Remove dir from argument. If ending in /, remove final / } elsif($replacement_string eq "{/.}") { $s =~ s:^.*/([^/]+)/?$:$1:; # Remove dir from argument. If ending in /, remove final / $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + } elsif($replacement_string eq "{/..}") { + $s =~ s:^.*/([^/]+)/?$:$1:; # Remove dir from argument. If ending in /, remove final / + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + } elsif($replacement_string eq "{/...}") { + $s =~ s:^.*/([^/]+)/?$:$1:; # Remove dir from argument. If ending in /, remove final / + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument + $s =~ s:\.[^/\.]*$::; # Remove .ext from argument } if($Global::JobQueue->quote_args()) { $s = ::shell_quote_scalar($s);
ところで、この手のやつで先頭にホスト名入れたい時ってどうします?
% get_host_list | parallel -I{} 'ssh {} "ps -unko -opid,pgrp,nice,etime,stime,stat,args | sort -k4 -nr | head -n3" | sed "s/^/{...}: /"'
とかかな。でも sed って quote とか escape とかめんどいし、パッと見なにしてるかわかんなくてやなんですよね。
あとは 'while read line; do echo "{}: $line"; done' とか? いやー。なんとか yes と paste 組み合わせてなんかできないかと試行錯誤して、諦めました。並列 ssh 専用だったら他に解は沢山あるし。
感想
よくこんなの GNU に入ったね、って思った。なんというか、流儀とかいろいろ。