Search code examples
rubyrakerake-taskpopen3

Real-time output of a rake task with popen3


It seems impossible to run a rake task from within a popen3 block while getting real-time output. All lines come at once at the end of the rake task. I'm trying to get real-time output from rake tasks though a popen3 block

cmd = 'rake perform_a_task'
Open3::popen3(cmd) do |std_in, std_out, std_err|
  std_out.each_line do |line|
    puts line
  end
end

How to reproduce

Proof of concept: the rake task

  1. Create a task as follow
task :print_and_wait do
  puts 'A'
  sleep 1
  puts 'B'
  sleep 1
  putc 'C'
end
  1. call the task from the command line

$ rake print_and_wait outputs 3 lines (A, B, and C) with a one second pause in between. As expected

Proof of concept 2: popen3

  1. Create a shell script
$ cat print_and_wait
#!/bin/bash
echo 'A'
sleep 1
echo 'B'
sleep 1
echo 'C'
  1. create a ruby scrip
$ cat print_and_wait.rb
require 'open3'

def exec_async(cmd)
  Open3::popen3(cmd) do |std_in, std_out, std_err|
    std_out.each_line do |line|
      puts line
    end
  end
end

exec_async './print_and_wait'
  1. run the ruby script

$ ruby print_and_wait.rb works as expected: output 3 line with a one second pause in-between

Where it does not work

  • edit the ruby script print_and_wait.rb and change exec_async './print_and_wait' to exec_async 'rake print_and_wait'
  • run $ ruby print_and_wait.rb
  • nothing outputs, and after 3 seconds all 3 lines are printed at the same time

I've tried several combinations but was never able to make it work as expected. Any idea why is this not working? Is this a bug?

Thanks


Solution

  • Adding $stdout.sync = true at the beginning of the rake task solved it.