3

I am trying to run a system command (rspec) and print its output to the terminal in real time and in colour, but I also want to capture its printed output in a string to use later.

At the moment it looks something like this:

cmd = "rspec #{ARGV.join(' ')}"
system cmd
raw = `#{cmd}`

This works, but since RSpec takes several seconds to complete, doubling that time is not insignificant. Is there any way to keep the system call printing to the terminal, but also have its output available for capture?

2
  • Have you tried print raw = `#{cmd}` ? Commented Dec 16, 2014 at 2:06
  • That doesn't print the output in colour or in real time. Commented Dec 16, 2014 at 2:58

2 Answers 2

2

It turns out there is a PTY.spawn method that is very similar to Open3#popen2e but also does colour. Here's my whole block:

require 'pty'

raw = ''
PTY.spawn(cmd) do |stdout_err, stdin, pid|
  begin
    while (char = stdout_err.getc)
      raw << char
      print char
    end
  rescue Errno::EIO # always raised when PTY runs out of input
  ensure
    Process.waitpid pid # Wait for PTY to complete before continuing
  end
end
Sign up to request clarification or add additional context in comments.

Comments

1

You should probably use Open3#popen2e. This method yields a stream for stdin, a stream for both stdout and stderr (they are merged), and a waiter thread.

You can safely close the stdin stream and ignore the waiter thread. You can read the merged stdout and stderr stream chunk by chunk.

1 Comment

Useful, but still not in colour.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.