Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby capture stderr output from bash script execution

I can currently redirect stdout to a string variable in ruby/rails by simply running the command in bash and setting the result to my string variable as follows.

val = %x[ #{cmd} ]

where cmd is a string that represents a bash command.

However, this only captures stdout, for I want to capture stderr and set it to a string in ruby -- any ideas?

like image 868
jab Avatar asked Aug 11 '14 13:08

jab


People also ask

How to capture stdout and stderr data from Ruby shell commands?

tl;dr If you want to run a shell command from Ruby and capture its stdout, stderr and return status, check out the Open3.capture3 method. If you'd like to process stdout and stderr data in a streaming fashion, check out Open3.popen3.

How do I run a shell command from Ruby?

tl;dr If you want to run a shell command from Ruby and capture its stdout, stderr and return status, check out the Open3.capture3 method. If you'd like to process stdout and stderr data in a streaming fashion, check out Open3.popen3. There are literally 492 ways to execute shell commands from ruby and each of them works slightly differently.

How to capture all output from a bash script?

A method I found to capture all output from any session is to start a new bash session and tee to a log file. its really useful for tracking more then just a script. ./myscript.sh | tee ./myscript.log #this will log only the output of the script. You can always invoke script inside a script to log everything.

Is it possible to run commands asynchronously in Ruby?

There is another option. One that gives you the ability to run commands asynchronously, and which gives you stdout, stderr, exit codes, and PIDs. Let's check it out! The oddly-named open3 module is part of Ruby's standard library.


2 Answers

Simply redirect it:

val = %x[ #{cmd} 2>&1 ]

If you want to capture output from stderr only, close the file descriptor for stdout after copying it to fd 2.

val = %x[ #{cmd} 2>&1 >/dev/null ]
like image 55
konsolebox Avatar answered Sep 28 '22 15:09

konsolebox


You can use Open3.popen3:

require 'open3'
stdin, stdout, stderr, wait_thread = Open3.popen3('ping -Z')
# => [#<IO:fd 9>, #<IO:fd 10>, #<IO:fd 12>, #<Thread:0x007fd3d30a0ce0 sleep>]

stderr.gets # => "ping: illegal option -- Z\n"
stdout.gets # => nil
like image 20
August Avatar answered Sep 28 '22 16:09

August