用于删除标准输出缓冲的“unbuffer”或“stdbuf”?

用于删除标准输出缓冲的“unbuffer”或“stdbuf”?

unbuffer(1) 和 stdbuf(1) 之间有区别吗?据我所知,unbuffer 所做的不仅仅是在开始时调用 libc 函数 set(X)buf,然后就顺其自然?

答案1

他们以完全不同的方式工作。

程序 unbuffer 使用expect 来运行指定的命令。因为expect创建了一个伪tty来附加到子进程的stdout,所以子进程可能会被愚弄,认为它应该使用行缓冲而不是块缓冲。当 isatty(stdout) 为 true 时,某些程序会改变其行为,而其他程序则不会,而且很难知道哪些会改变,哪些不会。

对于动态加载的二进制文件,程序 stdbuf 尝试将 libstdbuf 放在 libc 前面。其中 libstdbuf 重新定义了 libc stdio 调用的默认缓冲策略。

我发现了这一点

 apt-get source expect coreutils

并阅读每个程序的相关源代码。

答案2

长话短说

较旧的、已接受的答案仍然是正确的。根据我自己的经验,主要区别在于解除缓冲使用更简单,仅提供一个开关(-p)用于在管道中缓冲标准输入,这取消缓冲区不行。

虽然具体用例可能有所不同,但我会提供以下一般建议:

  1. 使用无缓冲的如果您需要缓冲标准输入并了解缓冲标准输入的限制,即如果管道提前退出或在 EOF 上提前终止,则挂起。
  2. 使用标准缓冲区当您需要单独控制输入、输出和错误 I/O 流的缓冲,并且不需要缓冲标准输入时。

来自 Coreutils 的 Stdbuf

标准缓冲区实用程序,它是 GNU 的一部分,为输入、输出和错误流提供单独的标志。值得注意的是,手册页提出了以下要点:

  1. 像 tee 这样本身调整缓冲区的命令将不受影响。
  2. 不使用 I/O 流的过滤器不受影响。
  3. 行缓冲对于标准输入无效。

所以,一般来说,标准缓冲区给你更多的控制权解除缓冲,但有一些注意事项。man 1 stdbuf(或man 1 gstdbuf在某些系统上)说:

注意:如果 COMMAND 调整其标准流的缓冲(例如“tee”),那么这将覆盖“stdbuf”的相应更改。另外,一些过滤器(如“dd”和“cat”等)不使用 I/O 流,因此不受“stdbuf”设置的影响...

BUGS
在GLIBC平台上,指定缓冲区大小,即使用完全缓冲模式将导致未定义的操作。

未从 Expect 中缓冲

无缓冲的命令,这是标准之一命令行示例工具,提供更少的旋钮。这对您来说可能有好处,也可能没有好处。就我个人而言,我更喜欢简单,除非我需要附加旋钮。另一方面,虽然标准缓冲区不适用于标准输入,无缓冲的使用该选项时可以-p

通常,unbuffer 不会从 stdin 读取。这在某些情况下简化了 unbuffer 的使用。要在管道中使用 unbuffer,请使用 -p 标志。

然而,这种行为带有一个警告和一些关于原因的进一步解释,如果您阅读man 1 unbuffered

如果向 unbuffer 提供输入的进程退出,则 unbuffer -p 可能无法正常工作。考虑:

             进程1 |取消缓冲-p process2 |流程3

如果 process1 退出,process2 可能尚未完成。 unbuffer 不可能知道等待 process2 的时间,并且 process2 可能永远不会完成,例如,如果它是一个过滤器。为了方便起见,unbuffer 在遇到来自其输入或 process2 的 EOF 时简单地退出。

在这种情况下,无缓冲的建议直接使用 Expect 或各种其他解决方法来手动调整管道。

相关内容