As other answers suggested, there are many ways of executing shell scripts from Ruby, but they're all not created equal. I'll try to explain all methods i know in more detail.
Backticks
`command arg1 arg2`
%x(command arg1 arg2)
Runs the command in a subshell and returns the output of the command. The command and its arguments are provided as a string delimited by backticks. An alternative syntax is %x(...)
which serves to avoid escaping issues, e.g. when you want to execute a command that contains backticks itself. The parentheses can be replaced by other delimiters such as []
, {}
, !!
, … in order to be able to work around just about any escaping issue.
Stderr is printed as normal, Stdout is suppressed. Returns the stdout output of the command. This means you can use the backtick notation to get the output of a command into a variable for further processing.
Kernel.exec
exec("command arg1 arg2")
exec("command", "arg1", "arg2")
Replaces the current process by running the command. The command and its arguments are provided as a normal string or as a comma delimited list of strings. Can be useful if you already have a list of arguments as an array. Output is left as is, i.e. will be printed to the console as if the command was run directly.
Kernel.system
system("command arg1 arg2")
system("command","arg1 arg2")
Like Kernel.exec
but runs in a subshell again. Returns true
if the process exited correctly (status 0), false
otherwise. This works great inside if
-statements.
Kernel.spawn
pid = spawn("command")
# do other stuff
Process.wait(pid)
Similar to Kernel.system
but will spawn a child process to run the specified command. The parent process will thus not wait for the command to finish executing unless Process.wait
is used. The return value is the PID of the spawned process.
IO.popen
io = IO.popen("command")
IO.popen("command") {|io| ... }
Runs the command in a child process again but allows for greater control over the IO. The child processes' stdout and stdin are connected to an IO object that is either accessible as the return value or a block parameter. If obtained via return value, the IO object should be closed after using it with io.close
.