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

Posted

技术标签:

【中文标题】GNU Parallel 和 Bash 函数:如何运行手册中的简单示例【英文标题】:GNU Parallel and Bash functions: How to run the simple example from the manual 【发布时间】:2014-07-11 22:27:24 【问题描述】:

我正在尝试学习 GNU Parallel,因为我有一个案例,我认为我可以轻松地并行化 bash 函数。所以在尝试学习时,我去了GNU Parallel manual 那里有an example...但我什至无法让它工作!也就是说:

(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”,例如,它会执行此操作。所以这个函数是有效的,只是没有......导出?

【问题讨论】:

你确定你有 GNU 并行,而不是 Tollef Fog Heen 的版本吗? @larsmans,它是 GNU 并行:(247) $ parallel --version GNU parallel 20140522 @shellter,我试过了。同样的答案。 它在我的 OSX 下的 Mac 上运行良好。您是否使用chmod +x tpar.bash 使tpar.bash 可执行 doit()前面加function有帮助吗 【参考方案1】:

您不能从定义它的 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=doit 之外,您可能还需要传递--env=SHELL(请注意,这假设bash 的路径在任何地方都是相同的)。

是的,这个奇怪的地方应该在手册中更突出地提到。在<em>command</em> argument的描述中有一个简短的注释,但不是很明确(它应该解释<em>command</em>单词以空格作为分隔符然后传递给$SHELL -c)和@987654339 @ 甚至没有在 environment variables 部分中列出。 (我鼓励您将此报告为错误;我不这样做是因为我几乎不使用此程序。)

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

【讨论】:

@larsmans export 在脚本顶部更简单,但确实为parallel 命令(及其子进程)设置SHELL 也是一种选择。【参考方案2】:

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

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

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

env_parallel --install

【讨论】:

注意env_parallel --install会将运行which env_parallel.bash的行附加到.bashrc,因此只需要运行一次。

以上是关于GNU Parallel 和 Bash 函数:如何运行手册中的简单示例的主要内容,如果未能解决你的问题,请参考以下文章

GNU Parallel:如何从gnu并行管道接收stdin,就像它来自文件一样?

GNU Parallel面向静默退出和无效选项错误

GNU Parallel 面临静默退出和无效选项错误

sh 使用cytominer_scripts和GNU parallel并行处理平板

gnu parallel + sed 编辑 csv 标题和内容

sh GNU Parallel + cUrl