From: Ed Hames Date: 2008-05-07T05:20:06+09:00 Subject: Re: Logging stdout/stderr/stdin of an spawn process (Open4::spawn) On Apr 29, 12:05 pm, Edgardo Hames wrote: > > I need to log all the input (typed by the user) and the stdout/stderr > of a process. The #script method below should behave pretty much like > the Unix script application. This way, my application can issue > several commands, show their output to the user an let them whatever > is needed. > > def script cmd, log >         # prepare $stdin to save its content into log >         # prepare $stdout to save its content into log >         # prepare $stderr to save its content into log >         status = Open4::spawn cmd, 'stdin' => $stdin, 'stdout' => > $stdout, 'stderr' => $stderr > end I finally managed to do it. Open4::spawn allows any object to be used as stdin/stdout/stderr as long as they support 'each', 'read', or 'to_s' or '<<'. So I just created a wrapper class that encapsulates two descriptors logging al I/O operations. Best regards, Edgardo # BEGIN SCRIPT require 'rubygems' require 'open4' class LoggingIO def initialize io, log @io = io @log = log end def gets(sep_string=$/) res = @io.gets(sep_string) log res res end def << obj res = @io << obj log obj res end def log obj str = obj ? obj.to_s : "(nil)\n" @log << str end private :log end def execute cmd, logfile = nil log = nil stdin = $stdin stdout = $stdout stderr = $stderr if (logfile) log = File.open(logfile, 'a+') stdin = LoggingIO.new($stdin, log) stdout = LoggingIO.new($stdout, log) stderr = LoggingIO.new($stderr, log) end status = Open4::spawn cmd, 'stdin' => stdin, 'stdout' => stdout, 'stderr' => stderr log.close if log status end # END SCRIPT