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

问题描述 投票:0回答:3

我正在尝试学习 GNU Parallel,因为我有一个案例,我认为我可以轻松地并行化 bash 函数。因此,在尝试学习的过程中,我查阅了GNU并行手册,其中有一个示例...但我什至无法让它工作!也就是说:

(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.

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

预计到达时间:根据评论者的建议(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”,它就会这样做。所以这个函数是有效的,只是没有...导出?

bash gnu-parallel
3个回答
44
投票

您无法从定义 shell 的外部调用 shell 函数。 shell函数是shell内部的一个概念。

parallel
命令本身无法访问它。

在 bash 中调用

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

根据消息“未找到命令”,您的首选 shell 似乎是 (t)csh。您需要告诉

parallel
来调用 bash。
parallel
调用由
SHELL
环境变量 1 指示的 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
甚至没有列在 环境变量 部分中。 (我鼓励您将此报告为错误;我不会这样做,因为我几乎从不使用这个程序。)

1 这是糟糕的设计,因为

SHELL
应该指示交互式命令行 shell 的用户界面首选项,而不是更改程序的行为。


15
投票

自版本 20160722 起,您可以改为使用

env_parallel
:

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

您只需将其添加到

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

env_parallel --install

0
投票

zsh
中,这有效:

 /usr/bin/parallel "$(where doit);doit" ::: 1 2 3 
© www.soinside.com 2019 - 2024. All rights reserved.