Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash - How to get STDOUT from a background ruby script

I need to run one ruby script in background, but I want to see its output in real time.

I wrote a simple test called loop.rb:

#!/usr/bin/env ruby

(1..4).each do
  puts "loop!"
  sleep 1
end

Whose foreground output is:

sony@sonymint:~/test$ ./loop.rb
loop!
loop!
loop!
loop!

But I can't see it in background:

sony@sonymint:~/test$ ./loop.rb &
[2] 3935
sony@sonymint:~/test$ 

However I can see the ping's output in background:

sony@sonymint:~/test$ ping google.com &
[2] 3734                                                                                                                                                                                                                                                                     
sony@sonymint:~/test$ PING google.com (64.233.190.113) 56(84) bytes of data.                                                                                                                                                                                                 
64 bytes from ce-in-f113.1e100.net (64.233.190.113): icmp_seq=1 ttl=42 time=79.6 ms                                                                                                                                                                                          
64 bytes from ce-in-f113.1e100.net (64.233.190.113): icmp_seq=2 ttl=42 time=79.5 ms                                                                                                                                                                                          
64 bytes from ce-in-f113.1e100.net (64.233.190.113): icmp_seq=3 ttl=42 time=81.7 ms                                                                            

So, two questions:

  1. Why can I see the output of ping and not the output of loop.rb?

  2. How to get the output of loop.rb in background in Bash?

UPDATE

@TomLord in comment is right: there is some odd system configuration. Locally my ruby is not a plain-installed ruby interpreter; it's a script which runs ruby inside a Docker container. So it can be a Docker issue. I tested on a machine with a plain-installed ruby interpreter and it worked fine. I'll investigate Docker buffering issues next.

like image 733
Sony Santos Avatar asked Nov 16 '25 11:11

Sony Santos


2 Answers

I've found the problem and the solution.

The problem:

  1. Why can I see the output of ping and not the output of loop.rb?

Because my local ruby is not a genuine ruby interpreter, but it's a script which runs ruby inside a docker container (easier to manage than using rvm IMHO). So it's a docker pipe buffer issue.

The solution:

  1. How to get the output of loop.rb in background in Bash?

By using the unbuffer command:

sony@sonymint:~/test$ unbuffer ./loop.rb & 
[3] 7262
sony@sonymint:~/test$ loop! 
loop! 
loop! 
loop! 
like image 179
Sony Santos Avatar answered Nov 19 '25 00:11

Sony Santos


Try putting this at the beginning of your script:

STDOUT.sync = true

This should disable buffering on the Ruby script's standard output. That buffering is normally done by your system's libc if it detects that it is not being run in an interactive shell.

like image 34
David Grayson Avatar answered Nov 19 '25 00:11

David Grayson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!