27

我正在尝试学习 GNU Parallel,因为我有一个案例,我认为我可以轻松地并行化 bash 函数。因此,在尝试学习时,我去了GNU Parallel 手册,那里有一个例子……但我什至无法让它工作!以机智:

(232) $ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(233) $ cat tpar.bash
#!/bin/bash

echo `which parallel`
doit() {
  echo Doing it for $1
  sleep 2
  echo Done with $1
}
export -f doit
parallel doit ::: 1 2 3
doubleit() {
  echo Doing it for $1 $2
  sleep 2
  echo Done with $1 $2
}
export -f doubleit
parallel doubleit ::: 1 2 3 ::: a b

(234) $ bash tpar.bash
/home/mathomp4/bin/parallel
doit: Command not found.
doit: Command not found.
doit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.

如您所见,我什至无法运行简单的示例。因此,我可能正在做一些非常愚蠢和基本的事情……但我不知所措。

ETA:根据评论者的建议(chmod +x,set -vx):

(27) $ ./tpar.bash

echo `which parallel`
which parallel
++ which parallel
+ echo /home/mathomp4/bin/parallel
/home/mathomp4/bin/parallel

doit() {
  echo Doing it for $1
  sleep 2
  echo Done with $1
}
export -f doit
+ export -f doit
parallel doit ::: 1 2 3
+ parallel doit ::: 1 2 3
doit: Command not found.
doit: Command not found.
doit: Command not found.
doubleit() {
  echo Doing it for $1 $2
  sleep 2
  echo Done with $1 $2
}
export -f doubleit
+ export -f doubleit
parallel doubleit ::: 1 2 3 ::: a b
+ parallel doubleit ::: 1 2 3 ::: a b
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.
doubleit: Command not found.

ETA2:请注意,我可以在脚本中调用'doit 1',比如说,它会这样做。所以这个函数是有效的,它只是没有......导出?

4

2 回答 2

40

您不能从定义它的 shell 外部调用 shell 函数。shell函数是shell内部的一个概念。parallel命令本身无法访问它。

在 bash 中调用export -f doit会通过环境导出函数,以便它被子进程拾取。但只有 bash 理解 bash 函数。(grand)*child bash 进程可以调用它,但不能调用其他程序,例如不能调用其他 shell。

根据消息“找不到命令”,您的首选 shell 似乎是 (t)csh。您需要告诉parallel调用 bash 。parallel调用环境变量¹指示的 shell SHELL,因此将其设置为指向 bash。

export SHELL=$(type -p bash)
doit () { … }
export -f doit
parallel doit ::: 1 2 3

如果您只想设置SHELL执行parallel命令而不是脚本的其余部分:

doit () { … }
export -f doit
SHELL=$(type -p bash) parallel doit ::: 1 2 3

我不确定如何处理远程作业,您可能还需要通过--env=SHELL--env=doit请注意,这假设到的路径bash在任何地方都是相同的)。

是的,应该在手册中更突出地提到这种奇怪之处。command在参数的描述中有一个简短的注释,但不是很明确(它应该解释这些command单词用空格作为分隔符连接,然后传递给$SHELL -c),SHELL甚至没有在环境变量部分列出. (我鼓励您将此报告为错误;我不这样做是因为我几乎从未使用过此程序。)

¹这是一个糟糕的设计,因为SHELL它应该指示交互式命令行 shell 的用户界面偏好,而不是改变程序的行为。

于 2014-05-22T19:33:05.580 回答
11

从版本 20160722 开始,您可以改用env_parallel

doit() { echo "$@"; }
echo world | env_parallel doit Hello

您只需env_parallel将其添加到.bashrc. 您可以.bashrc通过运行一次来​​添加它:

env_parallel --install
于 2018-01-10T23:31:04.473 回答