Redirecting STDOUT

Why doesn't this work?

(#executable is a function that returns a string that contains a test
application that spits out some data)

  def start
    pid = fork
    if pid.nil? # In child
      log = File.open(executable + ".log", "w")
      STDOUT.reopen(log)
      STDERR.reopen(log)
      exec executable # Start program
      exit
    else # In parent
      @pid = pid # Record new process id
      Process.detach @pid # If the process dies, let it die
      monitor # Start monitoring the process' status
    end
  end

Well, it works for the most part. The log file gets created, but
nothing gets written to it. Am I not redirecting output correctly?

Thanks,
Joe

Thanks,
Joe

Joe Van Dyk wrote:

Why doesn't this work?

(#executable is a function that returns a string that contains a test
application that spits out some data)

  def start
    pid = fork if pid.nil? # In child
      log = File.open(executable + ".log", "w")
      STDOUT.reopen(log)
      STDERR.reopen(log)
      exec executable # Start program
      exit
    else # In parent
      @pid = pid # Record new process id
      Process.detach @pid # If the process dies, let it die monitor # Start monitoring the process' status
    end
  end

Well, it works for the most part. The log file gets created, but
nothing gets written to it. Am I not redirecting output correctly?

Thanks,
Joe

Thanks,
Joe

Are you sure your "executable" is producing anything when launched the way you do it? You may try some STDERR.puts before "exec executable" to know for sure that something must be there. Also, I would do log.close before exec as the file descriptor is cloned anyway for stdout and stderr.

Gennady.

Why doesn't this work?

Disclaimer: I'm pretty good with Unix System stuff
but still learning on the Ruby so...

(#executable is a function that returns a string that contains a test
application that spits out some data)

  def start
    pid = fork
    if pid.nil? # In child
      log = File.open(executable + ".log", "w")
      STDOUT.reopen(log)
      STDERR.reopen(log)
      exec executable # Start program
      exit
    else # In parent
      @pid = pid # Record new process id
      Process.detach @pid # If the process dies, let it die
      monitor # Start monitoring the process' status
    end
  end

This worked for me (Mac OS X 10.4, Ruby 1.8.2). Check the permissions
on the log file. If was created in earlier tests as a read-only file maybe
that is why the program fails now.

If you have something like ktrace or truss on your system, trace
the ruby program and then look at the dump. You can see exactly
what system calls are being made (open/read/write/etc) and also
what errors, if any, are being returned.

Try using some standard program such as /bin/date instead of executable
just to make sure it isn't a problem with your test program. You'll
probably want a different path for the log file in that case.

If 'monitor' is going to watch the child process then just incorporate
calls to Process.wait(@pid) as part of 'monitor' instead of
Process.detach. If you have both Process.detach and monitor periodically
calling Process.wait, you'll never be sure which thread is going to
catch the exiting child.

Gary Wright

···

On Jun 27, 2005, at 1:37 PM, Joe Van Dyk wrote:

Nevermind, it does work!

My test application was the following Ruby application:

#!/bin/env ruby
while true
  puts "pid: #{Process.pid}, time: #{Time.now}"
  sleep 0.2
  puts
end

Does #puts not write to STDOUT by default?

···

On 6/27/05, gwtmp01@mac.com <gwtmp01@mac.com> wrote:

On Jun 27, 2005, at 1:37 PM, Joe Van Dyk wrote:
> Why doesn't this work?

Disclaimer: I'm pretty good with Unix System stuff
but still learning on the Ruby so...

> (#executable is a function that returns a string that contains a test
> application that spits out some data)
>
> def start
> pid = fork
> if pid.nil? # In child
> log = File.open(executable + ".log", "w")
> STDOUT.reopen(log)
> STDERR.reopen(log)
> exec executable # Start program
> exit
> else # In parent
> @pid = pid # Record new process id
> Process.detach @pid # If the process dies, let it die
> monitor # Start monitoring the process' status
> end
> end

This worked for me (Mac OS X 10.4, Ruby 1.8.2). Check the permissions
on the log file. If was created in earlier tests as a read-only file
maybe
that is why the program fails now.

If you have something like ktrace or truss on your system, trace
the ruby program and then look at the dump. You can see exactly
what system calls are being made (open/read/write/etc) and also
what errors, if any, are being returned.

Try using some standard program such as /bin/date instead of executable
just to make sure it isn't a problem with your test program. You'll
probably want a different path for the log file in that case.

If 'monitor' is going to watch the child process then just incorporate
calls to Process.wait(@pid) as part of 'monitor' instead of
Process.detach. If you have both Process.detach and monitor
periodically
calling Process.wait, you'll never be sure which thread is going to
catch the exiting child.

Gary Wright

Buffering. When you run this program with output
associated with the terminal, STDOUT is line buffered
so you see each line right after puts executes.

When you redirect STDOUT to a file, the IO is not
line buffered but instead buffered into blocks.
When I tested your program, I didn't see any output
in the file until puts had generated 4k worth of
data at which point it was flushed to the file
system.

You'll have to put in explicit calls to flush if
you expect to see the output in a different way or
change STDOUT to be line buffered.

Gary Wright

···

On Jun 27, 2005, at 4:52 PM, Joe Van Dyk wrote:

Nevermind, it does work!

My test application was the following Ruby application:

#!/bin/env ruby
while true
  puts "pid: #{Process.pid}, time: #{Time.now}"
  sleep 0.2
  puts
end

Does #puts not write to STDOUT by default?

Nevermind, it does work!

My test application was the following Ruby application:

#!/bin/env ruby

   STDOUT.sync = true

while true
puts "pid: #{Process.pid}, time: #{Time.now}"
sleep 0.2
puts
end

Does #puts not write to STDOUT by default?

you would've seen it eventually...

you also could do

   STDOUT.flush

after each write

cheers.

-a

···

On Tue, 28 Jun 2005, Joe Van Dyk wrote:
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================