有没有一种方法可以将每个输出都导入到文件中,就像监视终端以记录打印的所有内容一样?
此外,当我使用tee
时,它似乎会停止实际程序的输出。 我该怎么改变这个? 我希望保持正常的输出,并只使用其副本保存在文件中。
仅作为示例,我有这个ruby脚本:
100.times do |i|
puts i
end
运行$ruby script.rb | tee output.txt
命令可以很好地保存输出,但是它只会在整个过程运行完后才被打印出来。
如果您正在使用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
,您可以每次刷新文件并查看它每秒递增一个,即使脚本仍在运行。这是因为它正在“刷新”每个输出。
缺点:您只能在bash中使用script
命令来执行此操作。在这方面,您会创建一个依赖项;如果没有script
,或者它不像我的机器上的script
那样工作,则可能根本无法使用此方法。始终要谨慎处理依赖项。
有时候,您可能不会在bash中运行脚本,也可能没有可用的script
。那么怎么办?好吧,您只需创建一个打印到文件再打印到stdout的方法,而不考虑操作系统。然后它将每次刷新文件以确保其最新。
# 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
缺点:每次运行该脚本都会清除文件。如果您想保存长期日志以覆盖多个运行,则可能需要修改此小脚本。此外,如果没有文件权限,则此脚本将直接崩溃。这不是用于生产的,而仅仅是一个概念验证,供那些有兴趣实现此类系统的人使用。
您还可以通过将旧的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”的范畴,我坦率地说,除非你真的非常了解它,并且绝对必须这样做,否则我不建议实际操作。script
可以实现我的需求,但是我似乎无法从.sh脚本内部启动它(以便自动运行)。当我运行以下命令时,一直提示“找不到命令”:
#!/bin/bash $(script -f log.txt)
- Fábio Quelucichmod u+x whatever.sh
并确保在你的shell脚本中使用了脚本格式script -a -c "ruby whatever.rb" -f log.txt
? - Lukescript
的命令放在了.bashrc
文件中。这样做本身会创建一个无限循环,因为script
的工作方式是如此,所以你需要确保只调用它一次。使用$SHLVL == 1
的简单if语句就可以了。现在我可以自动记录发生在Shell上的所有事情。非常感谢你的帮助。 - Fábio Queluci
tee
在内部进行了缓冲。如果您只是正常运行它,标准输出流将在每行之后刷新,但是tee具有内部缓冲区,并且仅在该缓冲区足够大时才刷新到stdout。如果您改成运行100000.times do |i|,您会发现它会在运行完成之前打印。供您参考。 - scott_fakenameman script
可以帮助你。祝你好运。 - shellter