Bash — Как получить стандартный вывод из фонового скрипта ruby

#ruby #bash #background-process

#ruby #bash #фоновый процесс

Вопрос:

Мне нужно запустить один скрипт 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 amp;
[2] 3935
sony@sonymint:~/test$ 
  

Однако я вижу вывод ping в фоновом режиме:

 sony@sonymint:~/test$ ping google.com amp;
[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. Как получить вывод loop.rb в фоновом режиме в Bash?

Обновить

@TomLord в комментарии прав: существует некоторая странная конфигурация системы. Локально my ruby не является обычным интерпретатором ruby; это скрипт, который выполняется ruby внутри контейнера Docker. Так что это может быть проблемой Docker. Я тестировал на компьютере с обычным интерпретатором ruby, и он работал нормально. Далее я рассмотрю проблемы с буферизацией Docker.

Комментарии:

1. У меня работает просто отлично.

2. У меня тоже отлично работает. Возможно, у вас какая-то странная конфигурация системы? (Но даже тогда я понятия не имею, почему ping это сработает, если этого не произойдет?!)

3. superuser.com/questions/972968/…

4. Попробуйте использовать более длинную строку в тесте Ruby; возможно, у вас проблема с буферизацией, когда вы не даете программе работать достаточно долго, чтобы буфер заполнился и записался в стандартный вывод.

5. @TomLord вы правы, смотрите мое обновление.

Ответ №1:

Я нашел проблему и решение.

Проблема:

  1. Почему я могу видеть вывод ping , а не вывод loop.rb ?

Потому что мой local ruby не является подлинным интерпретатором ruby, но это скрипт, который выполняется ruby внутри контейнера docker (проще в управлении, чем с помощью rvm IMHO). Итак, это проблема с буфером канала docker.

Решение:

  1. Как получить вывод loop.rb в фоновом режиме в Bash?

С помощью unbuffer команды:

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

Ответ №2:

Попробуйте поместить это в начало вашего скрипта:

 STDOUT.sync = true
  

Это должно отключить буферизацию стандартного вывода скрипта Ruby. Такая буферизация обычно выполняется libc вашей системы, если она обнаруживает, что она не выполняется в интерактивной оболочке.