导出的 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
考虑以下(公认的荒谬)最小的非工作示例:
#!/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