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?
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.
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.
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.
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.
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 ]
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With