Unix tee命令如何将标准输出终端输出写入文件?如果输出太大怎么办?

4

我将一些工具的stdout重定向到tee命令,以便可以在终端和日志文件中看到当前的进度。

这是我运行工具并将其stdout提供给tee命令的代码片段,这个代码片段是从tcl脚本编写的。

$(EH_SUBMIT) $(ICC_EXEC) $(OPTIONS) -f ./scripts/$@.tcl | tee -i ./logs/$@.log

我可以在终端上看到当前的实时进度,但在日志文件中却看不到同样的观察结果!并且它会将stdout分块写入日志文件。
“tee”是如何工作的?它是按块还是按时间或两者兼而有之进行写入的? 如果是块,最小块大小是多少?如果是时间,最短持续时间是多少?
我需要解析实时日志条目以进行一些数据分析(通过“tail -f”读取日志文件,然后在日志文件增长时推送新数据)。

你的进度是写入标准输出(stdout)还是标准错误(stderr)?也许你的进程/操作系统在缓冲区未满之前不会刷新它们。 - knittl
你是如何确切地观察到日志文件以块的形式被写入的?例如,tail -f 命令每秒只轮询一次该文件,即使它们没有被分块写入,也会给人以分块写入的外观。 - Kees-Jan
@Kees-Jan 那是错误的。如果你传递 -s 选项,tail 只会睡眠。 - hek2mgl
@Kees-Jan 是的,我正在使用tail -f命令观察日志文件中的数据,它是以块的形式出现,同时在终端上逐行打印。 - Shantesh
1
@Kees-Jan 在cygwin环境中,由于其是内核特性,因此inotify不可用。在这种情况下,你是正确的!;) - hek2mgl
显示剩余6条评论
2个回答

5
除非程序自行处理缓冲,否则IO流的缓冲在libc中处理。标准行为是:如果输出到终端,则逐行缓冲输出;如果输出到非终端(即文件或管道),则以块方式缓冲输出。这就是为什么输出会按照您所描述的方式逐块显示在日志文件中的原因。此行为是为了性能优化而设计的。
在Linux上,可以使用stdbuf命令以调整的缓冲区运行程序。您需要像这样运行程序:
stdbuf -oL your_program >> your.log &
tail -f your.log

-oL 表示将标准输出按行缓冲。


谢谢你提供的另一种方法/解决方案,我会先尝试一下,但整个办公室的设置都是这样的,对我来说改变一些重要的东西很困难。 - Shantesh

3
根据POSIX规范中对于tee的说明,强调如下:
“tee”实用程序应将标准输入复制到标准输出,并在零个或多个文件中进行复制。 “tee”实用程序不应缓冲输出。
因此,“tee”不是您的问题。几乎可以确定,您的程序正在缓冲写入stdout的内容(当stdout不是TTY时,在许多编程语言中默认情况下使用)。
stdbuf -oL yourProgram | tee file

如果您的程序依赖于标准C库来确定其默认行为,那么它会被抑制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接