Logging stdout/stderr/stdin of an spawn process (Open4::spawn)

Hi dear rubyists,

I apologize for reposting this message, but I'm not sure if the
previous one did get to the mailing list.

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've seen some implementations of a #tee function or Tee class, but
they don't seem to work with spawn. What would you suggest?

Thanks in advance,
Ed

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

···

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