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
)用于在管道中缓冲标准输入,这取消缓冲区不行。
虽然具体用例可能有所不同,但我会提供以下一般建议:
- 使用无缓冲的如果您需要缓冲标准输入并了解缓冲标准输入的限制,即如果管道提前退出或在 EOF 上提前终止,则挂起。
- 使用标准缓冲区当您需要单独控制输入、输出和错误 I/O 流的缓冲,并且不需要缓冲标准输入时。
来自 Coreutils 的 Stdbuf
这标准缓冲区实用程序,它是 GNU 的一部分核心工具,为输入、输出和错误流提供单独的标志。值得注意的是,手册页提出了以下要点:
- 像 tee 这样本身调整缓冲区的命令将不受影响。
- 不使用 I/O 流的过滤器不受影响。
- 行缓冲对于标准输入无效。
所以,一般来说,标准缓冲区给你更多的控制权解除缓冲,但有一些注意事项。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 或各种其他解决方法来手动调整管道。