下面的代碼不打印tail -f
的輸出。爲什麼?我怎樣才能使它工作?ruby中的back-tick不適用於tail -f命令
#myApp.rb
`ls` #works fine
`tail -f filename` #does not work. why?
下面的代碼不打印tail -f
的輸出。爲什麼?我怎樣才能使它工作?ruby中的back-tick不適用於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')
是這裏有什麼區別?它不會返回命令的輸出,而會返回true(命令運行成功),false(失敗)或nil(命令執行失敗)。由於這個事實,命令的輸出沒有被重定向到運行tail -f
的return語句,它將把內容打印到標準輸出。
如果您可以將結果轉換爲標準輸出,那麼您可以簡單地將它放入一個線程塊。這樣,不斷增加的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。
您的文章是一個混亂的混亂,並描述了發生了什麼,而不是解釋爲什麼會發生。該op已經知道發生了什麼。 Downvoted。那些贊成你的帖子的人應該解釋他們爲什麼投了贊成票。你的推理是這樣的:如果你執行一個不返回值的命令,它不能寫入標準輸出;但是如果你使用ruby的system()方法來執行一個不返回值的命令,它將寫入stdout。咦? – 7stud
我還沒有說過,如果你執行一個不返回值的命令,它就不能寫入標準輸出。另外我從問題中沒有看到OP已經知道什麼以及他不知道什麼。感謝評論,但我會嘗試改進配方。 –
platzhirsch寫道:_沒有終止沒有返回值將被給予,所以什麼都不印._那是什麼意思呢?換句話說,命令的返回值還是與命令是否可以寫入標準輸出有關? – 7stud
它不起作用的原因是反引號分別調用System
來在反引號內運行命令。 如果你做了ps aux | grep tail
,你將能夠看到尾部進程實際上正在運行。
代碼沒有顯示任何輸出,因爲它等待尾部終止並繼續下一個語句 - 它沒有掛起,因爲它顯示尾部命令的輸出。
即使在正常操作中,您也必須執行ctrl+C
來關閉tail -f
命令的輸出。 -f
用於在文件增長時輸出附加數據,因此tail -f
將繼續運行。 嘗試使用ps aux | grep tail
的pid做kill -9 <pid_of_tail>
。然後你的ruby代碼的其餘部分將開始輸出結果。
該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`
...掛起,不輸出什麼,你可以推斷,反引號方法必須試圖捕捉命令的整個輸出。換句話說,反推方法不會從命令的標準輸出逐行讀取,即面向行的輸入。相反,反引號方法一次讀取面向文件的輸入,即一個文件。而且因爲命令tail -f some_file
從未完成寫入標準輸出,所以反引號方法永遠不會讀取文件結尾,並且在等待eof時掛起。
3)然而,讀取命令的輸出時間的文件不是讀取命令輸出的唯一方法。您也可以使用popen()一次讀取命令的輸出行:
my_prog。RB:
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