GNU parallel 忽略管道命令
GNU parallel ignores piped commands
我最终尝试使用并行作为一个简单的作业队列管理器,la here。这个想法似乎是将命令放在一个文件中,让 tail 读取文件(使用 -f 选项以便它不断寻找新行),然后将 tail 的输出通过管道传输到并行文件中。所以我试试
true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo {} ::: a b c >> jobqueue
但是没有任何反应。好的...测试一下,然后我就试试
cat jobqueue | parallel
这给出了
{} ::: a b c
同时
parallel echo {} ::: a b c
正确输出
a
b
c
那么,为什么 parallel 在从文件输入时忽略类似并行的语法,但在直接给出命令时却运行良好?
FWIW 这是版本 20160722,由于我在机器上没有 root 访问权限,所以我必须从源代码构建并安装到我的主目录中。
So why does parallel ignore the parallel-ish syntax when it was fed from a file, but runs fine when it's given the command directly?
因为这是规定要做的。您描述为 "syntax" 的内容在手册中定义为各种 命令行参数 及其部分。这些似乎主要针对在 parallel
的命令行上给出并行化命令并且程序输入由要操作的数据组成的情况。这是 xargs
程序的操作模式,它是 parallel
.
的灵感之一
事实是,你让事情变得比他们需要的更复杂。当您 运行 parallel
没有在其命令行上指定命令时,您通过其输入输入的命令不需要 需要 那种输入行操作parallel
本身提供的操作,一般来说,除了在它们自己的命令行上之外,它们不能以任何其他方式获取参数。当您 运行 parallel
处于该模式时,您只需向它提供您想要的确切命令 运行:
true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo a b c >> jobqueue
或
true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo a >> jobqueue
echo echo b >> jobqueue
echo echo c >> jobqueue
,取决于你到底在追求什么。
至于当您使用 tail -f
向 parallel
提供输入时似乎没有任何反应,我倾向于认为 parallel
正在等待更多输入。它的第一次读取没有 return 足够的数据来触发它调度任何作业,但标准输入仍然打开,因此它有理由认为会有更多的输入(这确实是合适的)。如果您继续为它提供作业,那么它很快就会获得足够的输入来开始 运行 处理它们。当您准备好关闭队列时,您必须 kill
tail
命令以便 parallel
知道它已到达其输入的末尾。
来自man parallel
:
There is a a small issue when using GNU parallel as queue system/batch manager: You have to submit JobSlot number of jobs before they will start, and after that you can submit one at a time, and job will start immediately if free slots are available. Output from the running or completed jobs are held back and will only be printed when JobSlots more jobs has been started (unless you use --ungroup or -u, in which case the output from the jobs are printed immediately). E.g. if you have 10 jobslots then the output from the first completed job will only be printed when job 11 has started, and the output of second completed job will only be printed when job 12 has started.
我已经设法拼凑出一个(充分)适用于我的情况的解决方案,这是对@John Bollinger 的回答的详尽阐述。
关键是我想将两个命令 和 的参数通过管道传递给 parallel
,并且这些参数会超过某个范围。例如,运行 command1 x
其中 x
范围超过 1..100
。现在 parallel
有一个有效的内置语法,即
parallel command1 ::: {1..100}
如果这就是我想做的,那很好。但我也有 command2
和 command3
等等,每个参数都有范围,我想将所有这些输入 parallel
进行管理。我希望能够在我已经开始后添加更多命令 运行 parallel
.
使用 tail
连续读取一些文件 jobqueue
正如我在问题中提出的那样,作为一个作业队列。要让 tail
和 parallel
在某些特殊字符串 endoffile
上退出,我使用
tail -f jobqueue | while read LINE
do
echo $LINE
[[ $LINE == *endoffile* ]] && pkill -P $$ tail
done | parallel -u -E endoffile
然后可以将命令输入 jobqueue
,但 :::
语法不再有效。如果我们以老式的方式做,事情确实有效:
for i in {1..100}
do
echo command1 $i >> jobqueue
done
然后最后事情可以用echo endoffile >> jobqueue
结束。
我最终尝试使用并行作为一个简单的作业队列管理器,la here。这个想法似乎是将命令放在一个文件中,让 tail 读取文件(使用 -f 选项以便它不断寻找新行),然后将 tail 的输出通过管道传输到并行文件中。所以我试试
true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo {} ::: a b c >> jobqueue
但是没有任何反应。好的...测试一下,然后我就试试
cat jobqueue | parallel
这给出了
{} ::: a b c
同时
parallel echo {} ::: a b c
正确输出
a
b
c
那么,为什么 parallel 在从文件输入时忽略类似并行的语法,但在直接给出命令时却运行良好?
FWIW 这是版本 20160722,由于我在机器上没有 root 访问权限,所以我必须从源代码构建并安装到我的主目录中。
So why does parallel ignore the parallel-ish syntax when it was fed from a file, but runs fine when it's given the command directly?
因为这是规定要做的。您描述为 "syntax" 的内容在手册中定义为各种 命令行参数 及其部分。这些似乎主要针对在 parallel
的命令行上给出并行化命令并且程序输入由要操作的数据组成的情况。这是 xargs
程序的操作模式,它是 parallel
.
事实是,你让事情变得比他们需要的更复杂。当您 运行 parallel
没有在其命令行上指定命令时,您通过其输入输入的命令不需要 需要 那种输入行操作parallel
本身提供的操作,一般来说,除了在它们自己的命令行上之外,它们不能以任何其他方式获取参数。当您 运行 parallel
处于该模式时,您只需向它提供您想要的确切命令 运行:
true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo a b c >> jobqueue
或
true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo a >> jobqueue
echo echo b >> jobqueue
echo echo c >> jobqueue
,取决于你到底在追求什么。
至于当您使用 tail -f
向 parallel
提供输入时似乎没有任何反应,我倾向于认为 parallel
正在等待更多输入。它的第一次读取没有 return 足够的数据来触发它调度任何作业,但标准输入仍然打开,因此它有理由认为会有更多的输入(这确实是合适的)。如果您继续为它提供作业,那么它很快就会获得足够的输入来开始 运行 处理它们。当您准备好关闭队列时,您必须 kill
tail
命令以便 parallel
知道它已到达其输入的末尾。
来自man parallel
:
There is a a small issue when using GNU parallel as queue system/batch manager: You have to submit JobSlot number of jobs before they will start, and after that you can submit one at a time, and job will start immediately if free slots are available. Output from the running or completed jobs are held back and will only be printed when JobSlots more jobs has been started (unless you use --ungroup or -u, in which case the output from the jobs are printed immediately). E.g. if you have 10 jobslots then the output from the first completed job will only be printed when job 11 has started, and the output of second completed job will only be printed when job 12 has started.
我已经设法拼凑出一个(充分)适用于我的情况的解决方案,这是对@John Bollinger 的回答的详尽阐述。
关键是我想将两个命令 和 的参数通过管道传递给 parallel
,并且这些参数会超过某个范围。例如,运行 command1 x
其中 x
范围超过 1..100
。现在 parallel
有一个有效的内置语法,即
parallel command1 ::: {1..100}
如果这就是我想做的,那很好。但我也有 command2
和 command3
等等,每个参数都有范围,我想将所有这些输入 parallel
进行管理。我希望能够在我已经开始后添加更多命令 运行 parallel
.
使用 tail
连续读取一些文件 jobqueue
正如我在问题中提出的那样,作为一个作业队列。要让 tail
和 parallel
在某些特殊字符串 endoffile
上退出,我使用
tail -f jobqueue | while read LINE
do
echo $LINE
[[ $LINE == *endoffile* ]] && pkill -P $$ tail
done | parallel -u -E endoffile
然后可以将命令输入 jobqueue
,但 :::
语法不再有效。如果我们以老式的方式做,事情确实有效:
for i in {1..100}
do
echo command1 $i >> jobqueue
done
然后最后事情可以用echo endoffile >> jobqueue
结束。