Note that there are some explanatory texts on larger screens.

plurals
  1. POContinuously read from STDOUT and STDERR in real time
    text
    copied!<p>Say we have a small application (<code>example.rb</code>) which behave like the following ruby code:</p> <pre><code>#!/usr/bin/env ruby done = false out =Thread.new do cnt = 0 while !done STDOUT.puts "out #{cnt}" cnt += 1 sleep 1 end end err = Thread.new do cnt = 0 while !done STDERR.puts "err #{cnt}" cnt += 1 sleep 1 end end while true i = STDIN.gets if i == "q\n" puts "Quiting" done = true break end end out.join err.join exit 42 </code></pre> <p>It print something to stdout and to stderr, it must be quited by writing "q\n" to stdin, and when it exit a value is returned in the return code.</p> <p>Now, I would like to write a small ruby script which can run this program in an external process, where stdout and stdin are captured, and when the external process should be terminated this is done by writing "q\n" to its stdin. This program is called <code>monitor.rb</code>.</p> <p>This is what I have tried here:</p> <pre><code>#!/usr/bin/env ruby require 'open3' class Monitor @cmd attr_accessor :return_code def initialize cmd @cmd = cmd end def run @runner_thread = Thread.new do Open3::popen3(@cmd) do |stdin, stdout, stderr, thread| puts "#{Time.now} #{@cmd} is running as pid: #{thread.pid}" stdin.sync = true; stdout.sync = true; stderr.sync = true; @stdin = stdin t_out = Thread.new do stdout.readlines do |l| puts "#{Time.now} STDOUT&gt; #{l}" end end t_err = Thread.new do stderr.readlines do |l| puts "#{Time.now} STDERR&gt; #{l}" end end thread.join t_err.join t_out.join @return_code = thread.value end end end def quit puts "Quiting" @stdin.puts "q" @stdin.close @runner_thread.join end end mon = Monitor.new "./example.rb" mon.run sleep 5 mon.quit puts "Return code: #{mon.return_code}" </code></pre> <p>Question 1: What is wrong with my code since the output of the external process is not being printed?</p> <p>Question 2: Can this be done in a more elegant way, and what would that look like?</p> <p>The code must be able to run on Linux and portability is not a priority, I uses ruby 2.0.</p> <p>When run <code>example.rb</code> in a terminal I get:</p> <pre><code>$ ./example.rb out 0 err 0 out 1 err 1 out 2 err 2 q Quiting </code></pre> <p>When I run the monitor application I get:</p> <pre><code>$ ./monitor.rb 2013-11-19 14:39:20 +0100 ./example.rb is running as pid: 7228 Quiting Return code: pid 7228 exit 42 </code></pre> <p>I expected the <code>monitor.rb</code> to print the output from <code>example.rb</code></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload