导出的 BASH 函数中的进程替换在 OS X 中不起作用?

Process substitution in exported BASH functions not working in OS X?

考虑以下(公认的荒谬)最小的非工作示例:

#!/usr/bin/env bash

test_func() {
  echo "" \
    | tee >(cat - > test) \
    | cat }

export -f test_func

parallel test_func :::: <(seq 1 4)

在 BASH 版本 3.2.57(1) 下 - 在 OS X 版本 10.11.1 上发布,这会产生以下错误:

sh: test_func: line 0: syntax error near unexpected token `('
sh: test_func: line 0: `test_func () {  echo "" | tee >(cat - > test) | cat -'
sh: error importing function definition for `test_func'

什么,在 OS X 中导出的 BASH 函数中没有进程替换?

我的想法太长了,无法发表评论,所以我将它们写在答案中。


首先,Bash 的 Bourne shell 仿真似乎存在缺陷(请注意 OS X 上的 /bin/sh 实际上是 Bash): 它试图导入在 bash 中导出的函数,这显然是错误的来源。要对此进行测试:

> func () { echo 'Exported function leaked into sh.'; } && export -f func && /bin/sh -c func
Exported function leaked into sh.

例如,一个简单的进程替换(在 Bourne shell 中不存在)会把它搞砸:

> func () { cat <(echo yay); } && export -f func && /bin/sh -c :
/bin/sh: func: line 0: syntax error near unexpected token `('
/bin/sh: func: line 0: `func () {  cat <(echo yay)'
/bin/sh: error importing function definition for `func'

注意我在 /bin/sh subshell 中没有做任何事情(我只 运行 :)。


至于为什么你在运行 parallel时看到这些错误信息,我想这是parallel方面不必要调用sh的问题,链中的某处。请注意,即使您硬编码 SHELL 甚至 PARALLEL_SHELL(请参阅手册页以获取此环境变量的文档),问题也不会消失,即 运行ning SHELL=/bin/bash parallel ...PARALLEL_SHELL=/bin/bash parallel ... 没有帮助,所以这显然是一个问题。但是,sh(或 sh 仿真模式下的 Bash)在非交互式调用时不会尝试读取任何启动文件,因此很难收集 [=16 的确切证据=] 在链中被调用(甚至是短暂的)。

我没有时间查看 parallel 的 10k 行源代码来证实我的推测(就此而言,这是一个奇怪的;我不明白为什么 sh应该被调用),因此您可能应该发送电子邮件至 bug-parallel@gnu.org 或 parallel@gnu.org 以获得一些专家意见。 Parallel 的 maintainer 也潜伏在这里。

已在 git 版本 [dd793ce] 中针对大多数系统进行了修复。

对于 dragonfly、freebsd、netbsd、qnx 和 unixware,您需要设置 PARALLEL_SHELL:

PARALLEL_SHELL=/bin/bash parallel --onall -S bsdserver 'func() { cat <(echo bash only construct); };export -f func; parallel func ::: ' ::: 1