Ruby on rails 在'irb'中,backticks抛出异常,但在'rails c'中,它们不';T 操作系统:Debian GNU/Linux 8 Ruby版本:2.4.1 Rails版本:5.1.4
我刚刚使用了Ruby on rails 在'irb'中,backticks抛出异常,但在'rails c'中,它们不';T 操作系统:Debian GNU/Linux 8 Ruby版本:2.4.1 Rails版本:5.1.4,ruby-on-rails,ruby,shell,backticks,Ruby On Rails,Ruby,Shell,Backticks,我刚刚使用了railsnew创建了一个全新的rails项目。在它的目录中,我使用irb,尝试对不存在的可执行文件执行shell命令,并引发异常: irb(main):001:0> `foobar` Errno::ENOENT: No such file or directory - foobar from (irb):1:in ``' from (irb):1 from /home/jackson/.rbenv/versions/2.4.1/bin/irb:11:i
railsnew
创建了一个全新的rails项目。在它的目录中,我使用irb
,尝试对不存在的可执行文件执行shell命令,并引发异常:
irb(main):001:0> `foobar`
Errno::ENOENT: No such file or directory - foobar
from (irb):1:in ``'
from (irb):1
from /home/jackson/.rbenv/versions/2.4.1/bin/irb:11:in `<top (required)>'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli/exec.rb:74:in `load'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli/exec.rb:74:in `kernel_load'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli/exec.rb:27:in `run'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli.rb:335:in `exec'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli.rb:20:in `dispatch'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli.rb:11:in `start'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/exe/bundle:32:in `block in <top (required)>'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/friendly_errors.rb:121:in `with_friendly_errors'
from /home/jackson/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/exe/bundle:24:in `<top (required)>'
from /home/jackson/.rbenv/versions/2.4.1/bin/bundle:22:in `load'
from /home/jackson/.rbenv/versions/2.4.1/bin/bundle:22:in `<main>'
这种不一致性似乎反映在Rails控制台之外。在我的Rails应用程序中,Backticks还返回nil
。这是一个问题,因为我们的一个gem中缺少命令的错误处理被破坏,因为它没有引发异常:
这种行为差异是故意的吗?如果没有,有什么问题,我该如何解决这个问题?您的问题似乎是Rails试图标准化行为:
class Object
# Makes backticks behave (somewhat more) similarly on all platforms.
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
# spawned shell prints a message to stderr and sets $?. We emulate
# Unix on the former but not the latter.
def `(command) #:nodoc:
super
rescue Errno::ENOENT => e
STDERR.puts "#$0: #{e}"
end
end
到处都是责怪:
- 用于替换核心方法的Rails
- 使用backticks而不是像
这样更安全、更干净的东西的gemOpen3
- Ruby没有指定
的行为方式(如果你足够自以为是的话,甚至可能会有反勾号)Kernel#`
Object.send(:remove_method, :'`')
因此,将使用内核中的标准反勾号。或者,如果您从未期望使用lt
命令,则可以替换gem的方法:
module LocalTunnel
class Client
def self.package_installed?
false
end
end
end
或者用您自己的实现替换LocalTunnel::Client.package\u installed?
,该实现通过检查backticks可能失败的各种方式,或者使用Open3
中的方法而不是backticks,围绕Rails覆盖工作。您还可以通过分解PATH
环境变量(使用File::PATH_SEPARATOR
)和File.executable?
手动查找lv
您使用哪一个kludge取决于您有什么可移植性要求,以及什么在您的环境中起作用。在我看来,从现在开始,我应该把backticks扔进垃圾箱。你有没有建议我通常如何用“更安全、更干净的东西,比如Open3
”,最好是用一个同步代码示例来替换backticks?我倾向于远离backticks,即system
的单参数版本,以及任何其他将调用shell的东西,太脆弱,容易出错,无法正确使用。您可能会使用Open3.capture2('some_命令','-arg')
而不是%x{some_命令-arg}
)。
module LocalTunnel
class Client
def self.package_installed?
false
end
end
end