#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
Итак, два вопроса:
-
Почему я могу видеть вывод
ping
, а не выводloop.rb
? -
Как получить вывод
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:
Я нашел проблему и решение.
Проблема:
- Почему я могу видеть вывод
ping
, а не выводloop.rb
?
Потому что мой local ruby
не является подлинным интерпретатором ruby, но это скрипт, который выполняется ruby
внутри контейнера docker (проще в управлении, чем с помощью rvm
IMHO). Итак, это проблема с буфером канала docker.
Решение:
- Как получить вывод
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 вашей системы, если она обнаруживает, что она не выполняется в интерактивной оболочке.