bash:强制exec'd进程具有无缓冲的stdout
我有一个脚本,如:
#!/bin/bash exec /usr/bin/some_binary > /tmp/my.log 2>&1
问题是some_binary
将所有的日志logging发送到标准输出,而缓冲使得我只能看到几行输出。 这是令人讨厌的东西卡住了,我需要看看最后一行说什么。
有没有办法使stdout无缓冲之前,我会执行这将影响some_binary,所以它有更多有用的日志logging?
(包装脚本只是在exec之前设置一些环境variables,所以perl或python中的解决scheme也是可行的。)
您可能会发现expect
的unbuffer
脚本可能会有所帮助。
GNU coreutils-8.5也有stdbuf
命令来修改I / Ostream缓冲。
http://www.pixelbeat.org/programming/stdio_buffering/
所以,在你的例子中,只需调用:
exec stdbuf -oL /usr/bin/some_binary > /tmp/my.log 2>&1
这将允许文本逐行显示(一旦一行完成,并在C)中的行尾"\n"
字符)。 如果您确实需要立即输出,请改用-o0
。
如果您不想通过unbuffer
命令引入依赖关系,那么这种方式可能更合意。 另一方面,如果你不得不愚蠢地认为它面临着一个真正的标准输出,那么就需要这种unbuffer
some_binary
方式。
一些命令行程序可以select修改它们的标准输出stream缓冲行为。 所以如果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的非缓冲脚本或修改程序源代码的替代方法,您也可以尝试使用脚本(1)来避免由pipe道引起的stdout打嗝:
请参阅: 欺骗一个应用程序,认为它的stdin是交互式的,而不是pipe道
# Linux script -c "[executable string]" /dev/null # FreeBSD, Mac OS X script -q /dev/null "[executable string]"
GNU Coreutils-8包含一个名为stdbuf的程序,它实质上是LD_PRELOAD技巧。 它在Linux上工作,据说在BSD系统上工作。
我search了互联网寻找答案,而这一切都为uniq
工作,这是太顽固了,除了stdbuf
以外的任何东西都缓冲:
{piped_command_here} | stdbuf -oL uniq | {more_piped_command_here}
环境variables可以将terminalIO模式设置为无缓冲。
导出NSUnbufferedIO = YES
这将设置C和O-Cterminal输出命令的无缓冲terminal。