ruby中的back-tick与tail -f命令不兼容

Bhu*_*van 6 ruby logging tail

下面的代码不打印输出tail -f.为什么?我怎样才能使它工作?

#myApp.rb
`ls`               #works fine
`tail -f filename`      #does not work. why?
Run Code Online (Sandbox Code Playgroud)

Kon*_*che 7

通过在执行的命令-f上使用follow选项tail不会立即终止.

-f, --follow[={name|descriptor}]
  output appended data as the file grows;
Run Code Online (Sandbox Code Playgroud)

与使用%x相反,使用反引号(或快捷方式)的想法system('...')是这些语句返回已执行命令的输出.这样您就可以将结果存储在变量中:

dir_content = `ls`
Run Code Online (Sandbox Code Playgroud)

tail -f产生另一个进程,此进程继续写入标准输出而不终止.因此,您的陈述永远不会完成.如果不完成语句,则无法返回值.如果要查看和输出不断增长的文件,请参阅问题的解决方案:

观察/阅读不断增长的日志文件.

或者,您可以system像这样运行命令:

system('tail -f filename')
Run Code Online (Sandbox Code Playgroud)

这有什么区别?它将返回true(命令运行成功),false(不成功)或nil(命令执行失败),而不是返回命令的outpout.由于事实,命令的输出没有重定向到运行tail -f它的return语句,它将内容打印到标准输出.

如果将结果输出到标准输出就可以了,只需将其放入Thread块即可.这样,不断增长的内容将filename写入标准输出,您可以继续执行其他Ruby代码.

Thread.new { system('tail -f filename') }
Run Code Online (Sandbox Code Playgroud)

如果您想要完全控制,请捕获输出以便将其存储以便在脚本的另一点进行检索,然后查看以下问题的答案,该问题描述了这种方法:

在Ruby中连续读取外部进程的STDOUT

它基于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
Run Code Online (Sandbox Code Playgroud)

最后,还有一种套接字方法.在Bash中打开一个套接字,或者使用socat,将输出tail -f传递给套接字并从套接字读入Ruby.