Ruby 为什么Open3.popen3在缺少可执行文件时返回错误错误?
我正在围绕CLI制作一个Ruby包装器。我发现了一个简洁的方法,Ruby 为什么Open3.popen3在缺少可执行文件时返回错误错误?,ruby,popen3,Ruby,Popen3,我正在围绕CLI制作一个Ruby包装器。我发现了一个简洁的方法,Open3.capture3(它在内部使用Open3.popen3),它允许我执行命令并捕获stdout、stderr和exit代码 我想检测的一件事是,如果找不到CLI可执行文件(并为此引发一个特殊错误)。我知道当找不到命令时,unixshell会给出退出代码127。 当我在bash中执行$foo时,会得到-bash:foo:command not found,这正是我想要显示的错误消息 考虑到这些,我编写了如下代码: requi
Open3.capture3
(它在内部使用Open3.popen3
),它允许我执行命令并捕获stdout、stderr和exit代码
我想检测的一件事是,如果找不到CLI可执行文件(并为此引发一个特殊错误)。我知道当找不到命令时,unixshell会给出退出代码127
。
当我在bash中执行$foo
时,会得到-bash:foo:command not found
,这正是我想要显示的错误消息
考虑到这些,我编写了如下代码:
require "open3"
stdout, stderr, status = Open3.capture3(command)
case status.exitstatus
when 0
return stdout
when 1, 127
raise MyError, stderr
end
但是,当我使用command=“foo”
运行它时,我得到一个错误:
Errno::ENOENT: No such file or directory - foo
/Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:193:in `spawn'
/Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:193:in `popen_run'
/Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:93:in `popen3'
/Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:252:in `capture3'
为什么会发生这种错误?我以为
Open3.capture3
应该直接在shell中执行该命令,那么为什么我不得到一个正常的STDERR和退出代码127
?Open3.popen3
委托给内核.spawn
,它根据命令传入的方式将命令发送给shell或直接发送给操作系统
commandline : command line string which is passed to the standard shell
cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
我们可能期望,如果调用Kernel.spawn(“foo”)
,它将被传递到shell(而不是操作系统)。但事实并非如此,Kernel.exec
的文档解释了原因:
If the string from the first form (exec("command")) follows these simple rules:
* no meta characters
* no shell reserved word and no special built-in
* Ruby invokes the command directly without shell
You can force shell invocation by adding ";" to the string (because ";" is a meta character).
最后一段揭示了解决方案
require "open3"
stdout, stderr, status = Open3.capture3(command + ";")
case status.exitstatus
when 0
return stdout
when 1, 127
raise MyError, stderr
end
旧但有效。我的添加如果您想添加参数,请将它们包括在命令中,例如,
Open3.capture3('ld--version'+';')
,如果您想这样添加,它将不起作用Open3.capture3('ld','--version'+';'))
,这是添加参数的推荐方法。