Edgardo Hames
5/6/2008 8:18:00 PM
On Apr 29, 12:05 pm, Edgardo Hames <eha...@gmail.com> 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