25

我有一个像这样的脚本:

#!/bin/bash
exec /usr/bin/some_binary > /tmp/my.log 2>&1

问题是some_binary将其所有日志记录发送到标准输出,并且缓冲使我只能看到几行块的输出。当某些事情卡住时,这很烦人,我需要看看最后一行说什么。

在我执行会影响 some_binary 的 exec 之前,有什么方法可以使 stdout 无缓冲,因此它具有更有用的日志记录?

(包装脚本只是在 exec 之前设置了一些环境变量,因此 perl 或 python 中的解决方案也是可行的。)

4

6 回答 6

34

GNU coreutils-8.5 也有stdbuf修改 I/O 流缓冲的命令:

http://www.pixelbeat.org/programming/stdio_buffering/

因此,在您的示例中,只需调用:

stdbuf -oL /usr/bin/some_binary > /tmp/my.log 2>&1

这将允许文本立即逐行显示(一旦一行"\n"以 C 中的行尾字符完成)。如果您真的想要立即输出,请-o0改用。

如果您不想expect通过unbuffer命令引入依赖关系,这种方式可能更可取。unbuffer另一方面,如果你不得不误some_binary以为它正面临一个真正的 tty 标准输出,则需要这种方式。

于 2010-07-30T16:36:03.907 回答
14

您可能会发现unbuffer随附的脚本expect可能会有所帮助。

于 2010-07-26T03:35:14.163 回答
11

一些命令行程序可以选择修改其标准输出流缓冲行为。如果 C 源代码可用,这就是要走的路……

# two command options ...
man file | less -p '--no-buffer'
man grep | less -p '--line-buffered'

# ... and their respective source code

# from: http://www.opensource.apple.com/source/file/file-6.2.1/file/src/file.c
if(nobuffer)
   (void) fflush(stdout);

# from: http://www.opensource.apple.com/source/grep/grep-28/grep/src/grep.c
if (line_buffered)
   fflush (stdout);

作为使用 expect 的 unbuffer 脚本或修改程序源代码的替代方法,您还可以尝试使用 script(1) 来避免管道引起的 stdout 打嗝:

请参阅:诱使应用程序认为其标准输入是交互式的,而不是管道

# Linux
script -c "[executable string]" /dev/null

# FreeBSD, Mac OS X
script -q /dev/null "[executable string]"
于 2010-07-26T16:57:06.897 回答
3

我在互联网上搜寻了答案,但这些都不起作用,因为uniq它太顽固而无法缓冲所有内容,除了stdbuf

{piped_command_here} | stdbuf -oL uniq | {more_piped_command_here}

于 2016-02-10T18:50:57.540 回答
2

GNU Coreutils-8 包含一个名为 stdbuf 的程序,它本质上执行 LD_PRELOAD 技巧。它适用于 Linux,据报道适用于 BSD 系统。

于 2013-12-23T10:57:28.833 回答
2

环境变量可以将终端 IO 模式设置为无缓冲。

导出 NSUnbufferedIO=YES

这将为 C 和 Ojective-C 终端输出命令设置终端无缓冲。

于 2016-07-19T23:00:56.170 回答