Running Command Line Commands Within Ruby Script

How to call shell commands from Ruby

This explanation is based on a commented Ruby script from a friend of mine. If you want to improve the script, feel free to update it at the link.

First, note that when Ruby calls out to a shell, it typically calls /bin/sh, not Bash. Some Bash syntax is not supported by /bin/sh on all systems.

Here are ways to execute a shell script:

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` , commonly called backticks – `cmd`

    This is like many other languages, including Bash, PHP, and Perl.

    Returns the result (i.e. standard output) of the shell command.

    Docs: http://ruby-doc.org/core/Kernel.html#method-i-60

    value = `echo 'hi'`
    value = `#{cmd}`
  2. Built-in syntax, %x( cmd )

    Following the x character is a delimiter, which can be any character.
    If the delimiter is one of the characters (, [, {, or <,
    the literal consists of the characters up to the matching closing delimiter,
    taking account of nested delimiter pairs. For all other delimiters, the
    literal comprises the characters up to the next occurrence of the
    delimiter character. String interpolation #{ ... } is allowed.

    Returns the result (i.e. standard output) of the shell command, just like the backticks.

    Docs: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Strings

    value = %x( echo 'hi' )
    value = %x[ #{cmd} ]
  3. Kernel#system

    Executes the given command in a subshell.

    Returns true if the command was found and run successfully, false otherwise.

    Docs: http://ruby-doc.org/core/Kernel.html#method-i-system

    wasGood = system( "echo 'hi'" )
    wasGood = system( cmd )
  4. Kernel#exec

    Replaces the current process by running the given external command.

    Returns none, the current process is replaced and never continues.

    Docs: http://ruby-doc.org/core/Kernel.html#method-i-exec

    exec( "echo 'hi'" )
    exec( cmd ) # Note: this will never be reached because of the line above

Here's some extra advice:
$?, which is the same as $CHILD_STATUS, accesses the status of the last system executed command if you use the backticks, system() or %x{}.
You can then access the exitstatus and pid properties:

$?.exitstatus

For more reading see:

  • http://www.elctech.com/blog/i-m-in-ur-commandline-executin-ma-commands
  • http://blog.jayfields.com/2006/06/ruby-kernel-system-exec-and-x.html
  • http://tech.natemurray.com/2007/03/ruby-shell-commands.html

How can I run a command line command from within a ruby file?

cmd = "ls > somefile.txt"
system( cmd )

or even just simply

system( "ls" )

Thus, you can use system.

How do i run Ruby script from command line ?

Try putting this in filename.rb:

def hi()
puts "hello"
end

hi

Then run your code in the command line: with ruby filename.rb

Run command line strings verbatim from ruby script

You can use backticks or system to access shell commands:

system 'cd /var/'

You’ll notice some difference in what they return (string vs exit status) and print.

But note that there are Ruby functions that already do some of the things you might be trying to do with the shell, e.g., Dir.chdir. In fact, the shell-outs mentioned above start a single subprocess that will lose track of having cd’d into a dir. So you’d have to string together commands that include a starting cd, like:

system 'cd /var; ls'

Execute shell commands from Ruby code

Ryan, there's several ways to call out to the system:

Backticks:
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(ruby -e 'p ARGV' '1 2' '3 4') # => "[\"1 2\", \"3 4\"]\n"

The system command. The difference here is that it passes stdin / out / err on through. (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. If you really need the big guns (it doesn't sound like you do), there's a gem open4.


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. 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.

How can I run a Ruby script from command line and get the response using Java code?

You can use this:

String[] commands = {"ruby","D:/MyProject/myruby.rb"};

Runtime rt = Runtime.getRuntime();

Process proc;
try
{
proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String s;

while ((s = stdInput.readLine()) != null)
{
System.out.println(s);
}
}
catch (IOException e)
{
e.printStackTrace();
}

Ruby Script to Command Line Tool

Ruby, because it's a general-programming language, makes it easy to create command-line scripts. Here's a basic script you can build upon:

#!/usr/bin/env ruby

require 'optparse'

args = {}
OptionParser.new do |opt|
opt.on('-i', '--input FILE', 'File to read') { |o| args[:file_in] = o }
opt.on('-o', '--output FILE', 'File to write') { |o| args[:file_out] = o }
end.parse!

abort "Missing input or output file" unless (args[:file_in] && args[:file_out])

File.write(args[:file_out], File.read(args[:file_in]))

Here's what's happening:

  • #!/usr/bin/env ruby is commonly called a "bang line". The shell will look for this line at the top of a file to determine what application can read the file and execute/interpret it. env is an application that will look through the user's PATH environment variable and return the first Ruby found as the Ruby to execute the script. Using this makes the script work with Rubies in the normal /usr/bin, /usr/local/bin or when managed by rbenv or RVM.
  • require 'opt parse' pulls in Ruby's command-line parser class OptionParser, which makes it easy to set up traditional flags, such as -i path/to/file/to/read, -o path/to/file/to/write, or long parameters, like --input or --output. It also automatically supplies the -h and --help flags to return formatted help text for the script. OptionParser is a bit of a learning-curve, so play with the complete example and you'll figure it out.

The rest should be pretty self-explanatory.

Traditionally, executables that are installed by the system go in /usr/bin. Executables we write, or add, go in /usr/local/bin, and I highly recommend sticking with that.

Some OSes don't automatically supply an entry for /usr/local/bin in the PATH, so you might need to modify your PATH setting in your ~/.bashrc, ~/.bash_profile or ~/.profile to allow the shell to locate the script.

Executable scripts need to have their executable flag set: chmod +x /path/to/executable is the basic command. See man chmod for more information.

I tend to leave the script's extension in place; Ruby scripts are "foo.rb", Python are "bar.py", etc. I do that because I prefer to have that extension as a hint of the language it's written in, but YMMV. The extension isn't necessary so go with what works for you.

Beyond all that, you might want to provide logging output, or output to the system's syslog. In the first case use Ruby's built-in Logger class, or the Syslog class in the second case.



Related Topics



Leave a reply



Submit