在Ruby中执行Bash语法错误执行命令,但它在shell中有效

时间:2017-07-07 22:18:29

标签: ruby linux bash

这是命令(我正在使用的是一个稍微变化的命令,但这会产生相同的错误)

HTTP_STATUS=$(curl -w "%{http_code}" -o >(cat >&3) 'http://example.org')

至于它的作用,它主要是从https://superuser.com/a/862395/334171复制的......重点是将HTTP请求的输出打印到终端,但是将状态代码存储在bash变量中。如果我在终端运行它,这工作正常。

然而,当我从Ruby运行它时,我得到sh: 1: Syntax error: "(" unexpected

cmd = <<-SH
  HTTP_STATUS=$(curl -w "%{http_code}" -o >(cat >&3) 'http://example.org')
SH
system cmd
`#{cmd}`

这两个都因上述错误而失败。

我想作为一种解决方法,我可以放入一个shell脚本并从Ruby调用它。但我很好奇为什么它不能以内联方式工作。

1 个答案:

答案 0 :(得分:0)

当您使用名称sh运行时,

bash 的行为会有所不同,因此即使/bin/bash确实是{/bin/sh/bin/sh/bin/bash的行为也会有所不同1}}。特别是,当 bash 作为sh运行时,它尽可能地符合POSIX规范,因此 bash - 特定扩展名(例如您的{{1}不会工作。此外,Ruby中的反引号和相关方法总是使用系统shell(即>(cat >&3))。总结:如果您在Ruby中使用shell,那么您几乎总是会使用严格的POSIX shell。

您可以明确调用/bin/sh并使用/bin/bash来提供命令。这可能会涉及到逃避的噩梦。

最好是使用Ruby标准库中的{{3}}绕过shell(所有这些)。 -c中有各种方法用于捕获和管理标准输出和标准错误,您不必担心引用任何内容,因为它不会成为涉及的shell。

顺便说一句,如果你真的想通过反引号或Open3设置一个环境变量,它就不会工作,因为环境变量是子进程的本地变量,所以父进程(你的Ruby脚本)或任何调用你的Ruby脚本的东西)永远不会看到它们。