Bash - 如何从后台 ruby 脚本获取 STDOUT

Bash - How to get STDOUT from a background ruby script

我需要 运行 一个 ruby 后台脚本,但我想实时查看它的输出。

我写了一个简单的测试,叫做 loop.rb:

#!/usr/bin/env ruby

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

谁的前台输出是:

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

但是我在后台看不到它:

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

但是我可以在后台看到 ping 的输出:

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                                                                            

那么,两个问题:

  1. 为什么我能看到ping的输出而看不到loop.rb的输出?

  2. 如何在Bash后台获取loop.rb的输出?

更新

@TomLord 的评论是对的:有一些奇怪的系统配置。在本地,我的 ruby 不是普通安装的 ruby 解释器;这是一个 运行s ruby 在 Docker 容器中的脚本。所以这可能是一个 Docker 问题。我在一台安装了普通 ruby 解释器的机器上进行了测试,它运行良好。接下来我将调查 Docker 缓冲问题。

我找到了问题和解决方案。

问题:

  1. 为什么我能看到 ping 的输出而不是 loop.rb 的输出?

因为我的本地 ruby 不是真正的 ruby 解释器,而是在 docker 容器内运行 ruby 的脚本(比使用 [=更易于管理 rvm恕我直言)。所以这是一个 docker 管道缓冲区问题。

解决方法:

  1. 如何在 Bash 的后台获取 loop.rb 的输出?

通过使用 unbuffer command:

sony@sonymint:~/test$ unbuffer ./loop.rb & 
[3] 7262
sony@sonymint:~/test$ loop! 
loop! 
loop! 
loop! 

尝试将其放在脚本的开头:

STDOUT.sync = true

这应该在 Ruby 脚本的标准输出上禁用缓冲。如果系统的 libc 检测到它没有在交互式 shell.

中被 运行,则该缓冲通常由系统的 libc 完成。