I’m trying to run thin start 2>&1 in a subprocess by running fork/exec, and I’m reassigning STDOUT to a pipe so I can feed output through.
However, I don’t get any output when Thin starts successfully. When it errors, I get the output in the wrong order—error text first, then the standard Thin startup messages.
I copied the code from Foreman, which handles this correctly. Any idea what’s going on?
Code:
reader, writer = IO.pipe
pid = fork do
Process.setpgrp
trap("INT", "IGNORE")
$stdout.reopen writer
reader.close
exec("thin start 2>&1")
end
Process.detach pid
until reader.eof?
puts reader.gets
end
Data sent to
$stdoutisn’t printed immediately — it’s buffered. On the other hand,$stderrisn’t buffered and when you write to it you see results immediately. Let’s see a minimal example.Save it as
test.rband replacethin startwithruby test.rb. Most probablystdoutwill be printed afterstderr. In order to fix it we’ll have to use theIO#sync=methodNow
stdoutwill be printed synchronously, just asstderris, and the resulting order of printed strings should be the intuitive one.Initial lack of output from your child Thin process might be caused by the fact that the child isn’t flushing data to STDOUT. First piece of data written to STDERR causes STDOUT to flush. Try adding
STDOUT.sync = truesomewhere in your application’s or Thin’s sources and see whether it helped.See also a discussion on ruby-forum.com titled capture output in real time.