I have a problem.
I want to run a ruby script from another ruby script and capture it\'s output information while letting it output to the screen too.
Have your script do its prompt output to stderr.
echo "Enter something" >&2
read answer
echo "output that will be captured"
This will be done for you if you use read -p
to issue the prompt:
read -p "Enter something" answer
echo "output that will be captured"
Try this:
rd, wr = IO::pipe
pid = Process.fork do
$stdout.reopen(wr)
rd.close
exec("command")
end
wr.close
rd.each do |line|
puts "line from command: #{line}"
end
Process.wait(pid)
Similar if you want to capture stderr. If you need to capture both it would a bit more difficult (Kernel.select
?)
Edit: Some explanation. This is an ancient Unix procedure: pipe + fork + calls to dup2 (reopen) depending on what you want. In a nutshell: you create a pipe as a means of communication between child and parent. After the fork, each peer close the pipe's endpoint it does not use, the child remaps (reopen) the channel you need to the write endpoint of the pipe and finally the parent reads on the read channel of the pipe.
STDOUT.print "Enter your password: "
password = gets.chomp
puts "Here is your password: #{password}"
Note STDOUT.print
require "stringio"
buffer = StringIO.new
$stdout = buffer
require "runner"
$stdout = STDOUT
buffer.rewind
puts buffer.read.match(/Here is your (password: .*)/).captures[0].to_s
Enter your password: hello
password: hello
I recently did a write-up on this here: Output Buffering with Ruby
You could use tee to write the contents to a file or a pipe, and read the file afterwards.
Have a look at POpen4.
It claims to be platform independent (but I do not think it works in jruby where you can use IO#popen
instead).
For script independent output logging you might want to enable it from the terminal emulator (shell container). screen -L OR xterm -l This will capture all output produced by any shell or program running inside the emulator, including output generated by your ruby scripts.