简体   繁体   English

从Ruby代码执行Shell命令

[英]Execute shell commands from Ruby code

Note: If you think of a better title/question, feel free to suggest it. 注意:如果您认为标题/问题更好,请随时提出建议。 I wasn't sure how to articulate this question in one brief sentence. 我不确定如何用一个简短的句子来表达这个问题。

I created a command line Mastermind game. 我创建了一个命令行Mastermind游戏。 To play the game, you type play.rb at the command line. 要玩游戏,请在命令行中键入play.rb

play.rb is a Ruby script that fires up the game. play.rb是一个可以启动游戏的Ruby脚本。 Within the script, the game is sent an interface, called CommandLineInterface . 在脚本内, CommandLineInterface游戏发送一个名为CommandLineInterface的接口。

If you want to play using a GUI (I'm using a Ruby GUI called Limelight), you cd into the limelight directory and type limelight open production and the GUI opens. 如果你想使用GUI玩(我使用Ruby的GUI称为Limelight系列),您cdlimelight目录和类型limelight open production和GUI打开。

There is a mastermind_game directory that contains a lib , a spec , and a limelight directory. 有一个mastermind_game目录,其中包含libspeclimelight目录。 The limelight directory contains a production directory. limelight目录包含一个production目录。

Now I'm making a few changes. 现在,我要进行一些更改。 You can pass arguments to the script at the command line. 您可以在命令行中将参数传递给脚本。 Either you enter play.rb "command line game" or play.rb "limelight game" . 您可以输入play.rb "command line game"play.rb "limelight game"

ARGV is an array of the arguments passed at the command line. ARGV是在命令行传递的参数数组。

if ARGV.include?("command line game")
    interface = CommandLineInterface.new
elsif ARGV.include?("limelight game")
    interface = LimelightInterface.new
end

If I want to play my command line game, I enter play.rb "command line game" and it works fine. 如果我想玩我的命令行游戏,请输入play.rb "command line game" ,它可以正常工作。

I want to be able to type play.rb "limelight game" at the command line and have that open the GUI. 我希望能够在命令行中输入play.rb "limelight game"并打开GUI。 In ARGV , the argument "limelight game" would be found so interface would be set to LimelightInterface.new . ARGV ,将找到参数"limelight game" ,因此将interface设置为LimelightInterface.new Within my LimelightInterface class I want the initialize method to open the GUI. 在我的LimelightInterface类中,我希望使用initialize方法打开GUI。 It should essentially have the same functionality as typing limelight open production at the command line. 它本质上应该具有与在命令行中键入limelight open production相同的功能。

I'm not sure if this is possible or how to do it, so any help would be appreciated! 我不确定这是否可行或如何实现,因此将不胜感激! Thanks! 谢谢!

EDITED: I'm trying to execute the command rvm use jruby by including this line in my script: 编辑:我试图通过在脚本中包含以下行来执行命令rvm use jruby

system("rvm use jruby")

I get back: "RVM is not a function, selecting rubies with 'rvm use ...' will not work." 我回来了:“ RVM不是功能,选择'rvm use ...'的红宝石将不起作用。”

Here's the first result from googling the title: http://tech.natemurray.com/2007/03/ruby-shell-commands.html 这是搜索标题的第一个结果: http : //tech.natemurray.com/2007/03/ruby-shell-commands.html

If that's not what you need, I don't understand the question. 如果那不是您所需要的,我不明白这个问题。

Ryan, there's several ways to call out to the system: Ryan,有几种方法可以调用系统:

Backticks: ruby -e 'p ARGV' '1 2' '3 4' # => "[\\"1 2\\", \\"3 4\\"]\\n" 反引号: ruby -e 'p ARGV' '1 2' '3 4' -e'p ARGV''1 2''3 ruby -e 'p ARGV' '1 2' '3 4' #=>“ [\\” 1 2 \\“,\\” 3 4 \\“] \\ n”

The %x literal (note that you can use any delimiter you like, you're not restricted to parentheses) %x文字(请注意,您可以使用任何喜欢的分隔符,但不限于括号)

%x(ruby -e 'p ARGV' '1 2' '3 4') # => "[\"1 2\", \"3 4\"]\n"

The system command. system命令。 The difference here is that it passes stdin / out / err on through. 此处的区别在于它通过stdin / out / err继续传递。 (the above return the stdout, this one prints it on your process' stdout). (上面的返回标准输出,这将它打印在您的进程的标准输出上)。

system('ruby', '-e p ARGV', '1 2', '3 4')
# >> ["1 2", "3 4"]

And if you need more sophisticated usage, something like open3 from the stdlib has gotten me pretty far. 而且,如果您需要更复杂的用法, 来自stdlib的open3之类的东西已经让我走了很多。 If you really need the big guns (it doesn't sound like you do), there's a gem open4 . 如果您真的需要大枪(​​听起来不像您那样),那么这里提供了一个gem4


Edit: 编辑:

It sounds like you're wanting to do something like this: 听起来您想做这样的事情:

require 'open3'

bash_script = <<SCRIPT
source "$HOME/.rvm/scripts/rvm"
rvm use jruby
ruby -v
exit
SCRIPT

out, err, status = Open3.capture3 'bash', stdin_data: bash_script
puts out
# >> Using /Users/joshcheek/.rvm/gems/jruby-1.6.7
# >> jruby 1.6.7 (ruby-1.8.7-p357) (2012-02-22 3e82bc8) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]

But honestly, I don't think it's a good solution for your situation, because there's many legitimate ways to set up jruby for your environment. 但老实说,我认为这不是解决您情况的好方法,因为有许多合法方法可以为您的环境设置jruby。 I think it would be better to just check that the limelight binary exists, and tell your user to fix their environment if it doesn't. 我认为最好只检查是否存在limelight二进制文件,并告诉用户修复不存在的环境。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM