GNU Parallel和Bash函数:如何运行手册中的简单示例

For*_*ran 17 bash gnu-parallel

我正在尝试学习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.
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我甚至无法获得运行的简单示例.因此,我可能正在做一些非常愚蠢和基本的事情......但我不知所措.

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.
Run Code Online (Sandbox Code Playgroud)

ETA2:注意,我可以在脚本中调用'doit 1',比如说,它会做到这一点.所以功能是有效的,它不是......导出的?

Gil*_*il' 28

您无法从定义它的shell外部调用shell函数.shell函数是shell中的一个概念.该parallel命令本身有没有办法来访问它.

调用export -f doitbash通过环境导出函数,以便子进程获取它.但只有bash才能理解bash函数.(宏)*子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
Run Code Online (Sandbox Code Playgroud)

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

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

我不知道该如何处理远程作业,您可能需要通过--env=SHELL--env=doit(注意,这个假设的路径bash是一样的无处不在).

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

¹ 这是一个糟糕的设计,因为SHELL它应该表示交互式命令行shell的用户界面首选项,而不是改变程序的行为.


Ole*_*nge 5

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

doit() { echo "$@"; }
echo world | env_parallel doit Hello
Run Code Online (Sandbox Code Playgroud)

您只需env_parallel将其添加到中即可激活.bashrc。您可以.bashrc通过运行一次将其添加到:

env_parallel --install
Run Code Online (Sandbox Code Playgroud)