DEV Community

Emili Parreno
Emili Parreno

Posted on

Calling system commands from within Ruby

Sometimes we need to execute system commands from within a Ruby app or script. You can find some methods in the Kernel module to accomplish this, but they behave slightly different. Let's take a look at all those methods and see what are their main differences.

exec("command")

This is the least common and least useful method for running external commands. exec replaces the current process (your Ruby script) by running the external command.

> exec('ls')
Enter fullscreen mode Exit fullscreen mode

We rarely want this behaviour so let's see different ways to run system commands.

command or %x{ command }

Backticks are the easiest and quickest way to run a command. Simply enclose the command you want to run in backticks like this:

> `ls`
=> "bin\ncode\n"
Enter fullscreen mode Exit fullscreen mode

If you prefer, you can get the same exact result using %x

> %x{ ls }
=> "bin\ncode\n"
Enter fullscreen mode Exit fullscreen mode

Both return the standard output of running the command in a subshell.

system("command")

If you want to explicitly check if the command was found and ran successfully, you can use the system command. Unlike the backtick or %x method, system will execute the command and return true if the command was successful (exit status 0), false if it was unsuccessful (exit status 1) or nil if the command execution failed.

> system('ls')
bin          code
=> true

> system('ls x')
ls: x: No such file or directory
=> false

> system('foo')
=> nil
Enter fullscreen mode Exit fullscreen mode

Special variables

For all of those methods mentioned above, you can access the PID and exit status of the unix process via the $? variable:

> system('ls')
bin       code
=> true

> $?.pid
=> 123

> $?.exitstatus
=> 0
Enter fullscreen mode Exit fullscreen mode

IO#popen

This method executes the specified command as a subprocess, as a result it will return an IO object containing both input and output, allowing you to use some convenient methods to access the output and the PID.

> command = IO.popen("ls -l")
> command.pid
=> 123
> command.readlines
=> ["total 8\n",
 "-rwxr-xr-x  1 emili  staff   40 Feb 11 20:25 hello.rb\n",
 "drwxr-xr-x  4 emili  staff  136 Jan 30 13:16 foo.rb\n"]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)