Код ниже не выводит вывод tail -f
. Зачем? Как я могу заставить его работать?back-tick in ruby не работает с командой tail -f
#myApp.rb
`ls` #works fine
`tail -f filename` #does not work. why?
Код ниже не выводит вывод tail -f
. Зачем? Как я могу заставить его работать?back-tick in ruby не работает с командой tail -f
#myApp.rb
`ls` #works fine
`tail -f filename` #does not work. why?
С помощью опции последующей -f
на tail
выполненную команду не будет немедленно прекратить.
-f, --follow[={name|descriptor}]
output appended data as the file grows;
Идея использования кавычки (или %x
ярлыка), в отличии от использования system('...')
является то, что эти заявления возвращают выходные данные выполненных команд. Таким образом, вы можете сохранить результат в переменной:
dir_content = `ls`
tail -f
порождает другой процесс, этот процесс продолжает писать на стандартный вывод без завершения. Следовательно, ваше заявление никогда не заканчивается. Без завершения инструкции значение не может быть возвращено. Если вы хотите посмотреть и распечатать растущий файл, см. Решение вопроса:
Watch/read a growing log file.
В качестве альтернативы, вы можете запустить команду через system
так:
system('tail -f filename')
В чем разница здесь? Вместо того, чтобы возвращать outpout команды, он вернет true (команда запускается успешно), false (неудачно) или nil (выполнение команды не выполнено). В связи с тем, что вывод команды не перенаправлен на оператор return, работающий tail -f
, он будет печатать контент на стандартный вывод.
Если вы в порядке с получением результатов на стандартный вывод, вы можете просто поместить его в блок Thread. Таким образом, растущий контент filename
записывается на стандартный вывод, и вы можете продолжать выполнять другой код Ruby.
Thread.new { system('tail -f filename') }
Если вы хотите иметь полный контроль, перехватывать вывод для того, чтобы сохранить его для поиска в другом месте вашего скрипта, то взгляните на ответ на следующий вопрос, который описывает такой подход:
Continuously read from STDOUT of external process in Ruby
Он основан на PTY модуля, который создает и управляет псевдо терминалов. В основном вы можете создать другой терминал через этот модуль. Тогда код мог бы выглядеть так:
require 'pty'
cmd = "tail -f filename"
begin
PTY.spawn(cmd) do |stdin, stdout, pid|
begin
# Do something with the output here: just printing to demonstrate it
stdin.each { |line| print line }
rescue Errno::EIO
puts "Errno:EIO error, but this probably just means " +
"that the process has finished giving output"
end
end
rescue PTY::ChildExited
puts "The child process exited!"
end
Наконец, есть также подход к сокету. Откройте сокет в Bash или с помощью socat
, выведите выходной сигнал tail -f
в сокет и прочитайте в Ruby из гнезда.
Ваш пост - путаный беспорядок и описывает, что происходит вместо того, чтобы объяснять, почему это происходит. Оп уже знает, что происходит. Downvoted. Люди, которые поддержали ваш пост, должны объяснить, почему они его поддержали. Ваши рассуждения выглядят примерно так: если вы выполняете команду, которая не возвращает значение, она не может записываться в stdout; но если вы используете метод system() ruby для выполнения команды, которая не возвращает значение, она будет записывать в stdout. А? – 7stud
Я не утверждал, что если вы выполняете команду, которая не возвращает значение, которое она не может записать в stdout. Также я не вижу на вопрос, что ОП уже знает и чего он не знает. Спасибо за комментарий, однако, я попытаюсь улучшить формулировки. –
platzhirsch wrote: _По окончании прекращения не будет возвращено никакого значения, и поэтому ничего не печатается. Что это значит? Или, говоря иначе, это возвращаемое значение команды или ее отсутствие, связанное с тем, может ли команда писать в stdout? – 7stud
Причина, по которой она не работает, заключается в том, что обратные шаги делают отдельный вызов System
для запуска команд в обратных тактах. Если вы делаете ps aux | grep tail
, вы сможете увидеть, что процесс хвоста фактически запущен.
Код не отображает никаких выходных данных, так как его ожидание завершения хвоста и переход к следующим операторам - его не висят, потому что он отображает вывод команды хвоста.
Даже при нормальной работе вы должны сделать ctrl+C
, чтобы закрыть выход команды tail -f
. -f
используется для вывода добавленных данных по мере роста файла, и, следовательно, tail -f
продолжает работать. Попробуйте сделать kill -9 <pid_of_tail>
, используя pid из ps aux | grep tail
. Затем оставшаяся часть вашего рубинового кода начнет выводить результат.
ls
, tail without -f
вызывает работу, потому что они заканчиваются самостоятельно.
Если вы заинтересованы в этом хвост из рубина, вы можете посмотреть на этот file-tail
драгоценный камень http://flori.github.io/file-tail/doc/index.html
1) Согласно кавычку документы,
`cmd`
Returns the standard output of running cmd in a subshell.
Так что, если вы пишете:
puts `some command`
Затем рубин должен печатать какие-либо командные выходы.
2) В соответствии с хвостового человека страниц:
The tail utility displays the contents of file...to the standard
output.
Но команды:
puts `tail -f some_file`
не печатает ничего, несмотря на то, что работает:
$ tail -f some_file
посылает выход к стандартным выходам. На страницах хвостового оператора также указаны
The -f option causes tail to not stop when
end of file is reached, but rather to wait
for additional data to be appended to the
[the file].
Что это значит? И как это имеет отношение к проблеме?
Поскольку запуск программы:
puts `tail -f some_file`
... виснет и не выводит ничего, можно сделать вывод, что метод должен быть обратные кавычки пытается захватить весь вывод команды. Другими словами, метод обратных шагов не читается по строке из стандартного вывода команды, т. Е. ориентированный на линию вход. Вместо этого метод backticks считывает входной файл, ориентированный на ориентацию, то есть файл за раз. И поскольку команда tail -f some_file
никогда не заканчивает запись на стандартный вывод, метод backticks никогда не читает конец файла, и он зависает, пока он ждет eof.
3) Однако считывание вывода команды файла - это не единственный способ прочитать вывод команды. Вы также можете прочитать вывод команды по строке, используя popen():
my_prog.гь:
IO.popen('tail -f data.txt') do |pipe|
while line = pipe.gets do #gets() reads up to the next newline, then returns
puts line
end
end
--output(terminal window 1):--
$ ruby my_prog.rb
A
B
C
<hangs>
--output(terminal window 2):--
echo 'D' >> data.txt
--output(terminal window 1):--
A
B
C
D
<hangs>
эхо страницы человека:
The echo utility writes any specified operands...followed
by a newline (`\n') character.
работал как очарование спасибо :) – Faizan
Является '«имя файла»' буквальное имя файла (или фиктивной имя, используемое только для вашего вопроса)? Или это имя переменной, которая содержит строку? – sawa
'filename' является манекеном для вопроса – Bhuvan