将每个 bash 输出通过管道传输到文件

Pipe every bash output to file

有没有办法将每个输出通过管道传输到一个文件,比如监控终端以记录所有打印的内容?

此外,当我使用 tee 时,它似乎停止了实际程序的输出。我怎样才能改变这个?我想保持正常输出,只是用它的副本保存在文件中。

举个例子,我有这个 ruby 脚本:

100.times do |i|
  puts i
end

并且运行 $ruby script.rb | tee output.txt 会很好地保存输出,但它只会在整个过程运行后打印出来。

用 Bash

如果您使用 bash(根据您的标签),您可以 运行 script -a -c "ruby your_script.rb" -f your_file.out.

因此,例如,如果您编写了以下脚本,请将其保存为 test.rb:

# test.rb
i = 0
while true do
    i += 1
    puts i
    sleep 1
end

然后 运行 script -a -c "ruby test.rb" -f test.out,你每次都可以刷新文件并看到它每秒递增一个,即使脚本是 在媒体资源中;也就是说,还是运行ning。这是因为每次输出都是"flushing"

缺点: 您只能使用 bash 中的 script 命令执行此操作。在这方面,您创建了依赖关系;如果 script 不存在,或者它不像我机器上的 script 那样工作,那么这种方法可能根本不起作用。始终警惕依赖性。

自己做 Ruby

有时,您可能不会 运行 在 bash 上安装您的脚本,并且 script 可能不可用。然后怎样呢?好吧,您可以只创建一个打印到文件然后打印到标准输出的方法,而不管操作系统是什么。然后它会每次刷新文件以确保它是最新的。

# print_to_file.rb
class PrintOutputToFile
  def self.file
    @@file ||= File.open("my_output.log", "w")
  end

  def self.puts! some_data
    file.write "#{some_data}\n"
    file.flush
    puts some_data
  end
end

i = 0
while true do
  i += 1
  PrintOutputToFile.puts! i
  sleep 1
end

缺点: 这将在您每次 运行 时清除文件。如果你想保留一个保存了很多 运行s 的长期日志,你可能需要修改这个小脚本。此外,如果您没有文件权限,此脚本将彻底崩溃。这 不是 用于生产,而只是作为对那些有兴趣实施这样的系统的人的概念验证。

Ruby 本身的另一种方法

您也可以通过将旧的 puts 方法复制到 proc 中,然后覆盖核心 puts 方法以写入日志文件,但以调用原始 puts 方法结束。

@@old_puts = method(:puts).to_proc
def puts(output)
  @@file ||= File.open("your_log.txt", "w")
  @@file.write "#{output}\n"
  @@old_puts.call output
  @@file.flush
end

缺点: 这是一个超越 hacky 的步骤,我 f运行kly 不建议实际这样做,除非你真的,真的知道你在做什么并且绝对必须。