我目前正在测试 gnu parallel,以使用 bash 在多个服务器上分发比较命令。在其最基本的功能中,此比较命令需要两个输入进行比较(oracle 数据库访问),并通过 -o 要求输出文件名。程序至少需要执行一个操作加载、保存或直接上传。
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
由于某些我无法理解的原因,比较程序无法正确处理转义的空格。在 bash 中执行此命令会导致完全相同的错误消息。删除 -o 标志后的转义(我可以将 -o 移至并行命令)会导致“参数过多”错误。删除所有转义可按预期执行命令。
是否可以告诉 parallel 不要在命令调用上打印转义符?我似乎在文档中找不到任何内容,只是这是预期的默认行为,如parallel --shellquote
答案1
GNU Parallel 将输入视为单个参数并将其括起来,以便您可以安全地使用文件名,例如:
My brother's 12" records costs 30$ each.txt
在您的情况下,您希望 shell 解析该参数,因此空格将不会被引用:
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*
这会将所有输入*与所有输入*进行比较。--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