There are multiple ways to run system commands from Ruby.
They are system
, using backticks (‵), using %x(),
using exec
, or the more advanced option of using Open3
. All of them behave in different ways.
system
The system method calls a system program. You have to provide the command as a string argument to this method. For example:
>> system("date") Sat 4/10/2021 9:11:38 => true
Note: In Windows, the date
command also takes the input to change the system date after displaying the current system date. Press Enter
to continue
The invoked program will use the current STDIN
, STDOUT
and STDERR
objects of your Ruby program. In fact, the actual return value is either true
, false
or nil
. In the example the date was printed through the IO object of STDIN
. The method will return true if the process exited with a zero status, false if the process exited with a non-zero status and nil if the execution failed.
As of Ruby 2.6, passing exception: true will raise an exception instead of returning false or nil:
>> system('invalid') => nil >> system('invalid', exception: true) Traceback (most recent call last): ... Errno::ENOENT (No such file or directory - invalid)
Another side effect is that the global variable $?
is set to a Process::Status object. This object will contain information about the call itself, including the process identifier (PID) of the invoked process and the exit status.
>> system("date") Wed Sep 4 22:11:02 CEST 2013 => true >> $? => #<Process::Status: pid 15470 exit 0>
backticks
Backticks (‵) call a system program and return its output. As opposed to the first approach, the command is not provided through a string, but by putting it inside a backticks pair.
>> `date` => Sat 4/10/2021 9:13:30
Note: Again, in Windows, since an input is expected, the command doesn’t show anything until Enter
is pressed
The global variable $?
is set through the backticks, too. With backticks you can also make use string interpolation.
%x()
Using %x
is an alternative to the backticks style. It will return the output, too. Like its relatives %w
and %q
(among others), any delimiter will suffice as long as bracket-style delimiters match. This means %x(date)
, %x{date}
and %x-date-
are all synonyms. Like backticks %x
can make use of string interpolation.
exec
By using Kernel#exec
the current process (your Ruby script) is replaced with the process invoked through exec
. The method can take a string as argument. In this case the string will be subject to shell expansion. When using more than one argument, then the first one is used to execute a program and the following are provided as arguments to the program to be invoked.
Open3.popen3
Sometimes the required information is written to standard input or standard error and you need to get control over those as well. Here Open3.popen3 comes in handy:
require 'open3' Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread| pid = thread.pid puts stdout.read.chomp end
Also see ruby Open3 module
Reference: stackoverflow.com/a/18623297/33581
From another answer from Stackoverflow – https://stackoverflow.com/a/6338954/33581
They do different things. exec replaces the current process with the new process and never returns. system invokes another process and returns its exit value to the current process. Using backticks invokes another process and returns the output of that process to the current process.
Lastly, this wonderful diagram, again from Stackoverflow – https://stackoverflow.com/a/31572431/33581
Another response from Stackoverflow: https://stackoverflow.com/a/13849830/33581
You can just puts
the output:
puts `mocha`
The backticks ` are calling the command mocha and return the output of the command.
You may also use %x{}
puts %x{mocha}
Or you use system
:
system('mocha')
Or you store the output for later use in a variable:
output = `mocha` puts output
As mentioned by user Cody Poll below that answer
One thing to keep in mind is that
puts `mocha`
won’t print in real time – it’ll wait until the entire command is done, and then print the final result. Also, loss of color. For those, you should usesystem('mocha')