
現在、bash を使用して複数のサーバーに比較コマンドを分散する GNU Parallel をテストしています。最も基本的な機能では、この比較コマンドは比較する 2 つの入力 (Oracle データベース アクセス) を受け取り、-o 経由で出力ファイル名を必要とします。プログラムでは、少なくとも 1 つのアクションのロード、保存、または直接アップロードが必要です。
compare -o cmp.input1.input2.dat Input1 Input2
私はこれらの入力ペアを数千個持っており、すべての組み合わせを含むファイルを作成し、各行に出力ファイル名とプログラムに必要なデータベース識別子を含めます。
#test_parallel
-o cmp.input1.input2.dat Input1 Input2
-o cmp.input1.input3.dat Input1 Input3
-o cmp.input2.input3.dat Input2 Input3
[...]
並列でコマンドを実行すると、比較コマンドが失敗する
parallel -a test_parallel "compare {}"
ERROR: No action specified for results (load, save or direct upload)
usage: compare [-u][-o <file>] query target
モードを使用すると--dryrun
、並列実行は次のようになります。
compare -o\ cmp.input1.input2.dat\ Input1\ Input2
理由はわかりませんが、エスケープされた空白は compare プログラムによって正しく処理されません。このコマンドを bash で実行すると、まったく同じエラー メッセージが表示されます。-o フラグの後のエスケープを削除すると (-o を並列コマンドに移動できます)、「引数が多すぎます」というエラーが発生します。すべてのエスケープを削除すると、コマンドは期待どおりに実行されます。
コマンド呼び出し時にエスケープを出力しないようにparallelに指示することは可能ですか?ドキュメントには何も記載されていないようですが、これは期待されるデフォルトの動作であり、parallel --shellquote
答え1
GNU Parallel は入力を単一の引数として扱い、引用符で囲むため、次のようなファイル名を安全に使用できます。
My brother's 12" records costs 30$ each.txt
あなたの場合、引数をシェルで解析したいので、スペースは引用符で囲まれません。
parallel -a test_parallel eval compare {}
または、スペースで分割することもできます。
parallel --colsep ' ' -a test_parallel compare {1} {2} {3} {4}
しかし、すべてとすべてを比較したいのであれば、もっとエレガントに行うことができます。
parallel cmp -o ../out/cmp.{1}.{2} {1} {2} ::: Input* ::: Input*
これは、すべての Input* をすべての Input* と比較します。これにより、--results
出力をディレクトリ内に適切に構造化できます。
parallel --results out/ cmp {1} {2} ::: Input* ::: Input*
cmp InputY InputX
しかし、すでに実行した後に実行をスキップしたい場合はcmd InputX InputY
、次のようにします。
parallel --results out/ cmp {=1' $arg[1] ge $arg[2] and $job->skip();' =} {2} ::: Input* ::: Input*
編集:
バージョン20190722では、機能が導入されましたuq
。
parallel -a test_parallel compare {=uq=}
uq
は perl 関数です。呼び出されると、GNU Parallel は置換文字列を引用符で囲みません。したがって、引用符で囲まれた置換文字列と引用符で囲まれていない置換文字列を混在させることができます。
parallel echo {} = {=uq=} ::: \$PWD
# You can change $_ if you want: uq() is a normal perl function
parallel echo {}ME = '{=uq(); $_.="ME"=}' ::: \$HO \$LOGNA