bash:强制执行的进程具有无缓冲的标准输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3332045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:23:32  来源:igfitidea点击:

bash: force exec'd process to have unbuffered stdout

bashloggingexecunbuffered-output

提问by bstpierre

I've got a script like:

我有一个像这样的脚本:

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

Problem is that some_binarysends all of its logging to stdout, and buffering makes it so that I only see output in chunks of a few lines. This is annoying when something gets stuck and I need to see what the last line says.

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

Is there any way to make stdout unbuffered before I do the exec that will affect some_binary so it has more useful logging?

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

(The wrapper script is only setting a few environment variables before the exec, so a solution in perl or python would also be feasible.)

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

采纳答案by Paused until further notice.

You might find that the unbufferscript that comes with expectmay help.

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

回答by zaga

GNU coreutils-8.5 also has the stdbufcommand to modify I/O stream buffering:

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

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

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

So, in your example case, simply invoke:

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

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

This will allow text to appear immediately line-by-line (once a line is completed with the end-of-line "\n"character in C). If you really want immediate output, use -o0instead.

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

This way could be more desirable if you do not want to introduce dependency to expectvia unbuffercommand. The unbufferway, on the other hand, is needed if you have to fool some_binaryinto thinking that it is facing a real tty standard output.

如果您不想引入对expectviaunbuffer命令的依赖,这种方式可能更可取。unbuffer另一方面,如果您不得不误some_binary以为它面对的是真正的 tty 标准输出,则需要这种方式。

回答by trevor

Some command line programs have an option to modify their stdout stream buffering behaviour. So that's the way to go if the C source is available ...

一些命令行程序可以选择修改它们的标准输出流缓冲行为。所以如果 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);

As an alternative to using expect's unbuffer script or modifying the program's source code, you may also try to use script(1) to avoid stdout hiccups caused by a pipe:

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

See: Trick an application into thinking its stdin is interactive, not a pipe

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

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

# FreeBSD, Mac OS X
script -q /dev/null "[executable string]"

回答by Dexter Legaspi

I scoured the internets for an answer, and none of this worked for uniqwhich is too stubborn to buffer everything except for stdbuf:

我在互联网上搜索了答案,但这些都不起作用,uniq因为它太固执以至于无法缓冲除以下内容之外的所有内容stdbuf

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

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

回答by EKM

An environment variable can set the terminal IO mode to unbuffered.

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

export NSUnbufferedIO=YES

导出 NSUnbufferedIO=YES

This will set the terminal unbuffered for both C and Ojective-C terminal output commands.

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

回答by Otheus

GNU Coreutils-8 includes a program called stdbuf which essentially does the LD_PRELOAD trick. It works on Linux and reportedly works on BSD systems.

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