通过在tail 上使用跟随选项-f,执行的命令不会立即终止。
-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的返回语句,它会将内容打印到标准输出。
如果您可以将结果输出到标准输出,您可以简单地将其放入 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。