Par*_*hot 6 shell grep pipe buffer
以下内容在 bash 中不会产生任何内容:
while true ; do upower -d ; sleep 1 ; done | grep percentage | uniq
Run Code Online (Sandbox Code Playgroud)
我发现这个链中的最后一个或什至倒数第二个程序是什么并不重要。倒数第二个程序总是产生预期的输出,而最后一个程序总是无法产生任何东西。
如果我将 while 循环包装在子外壳中(通过( while ... done )
),或者将除最后一个命令之外的所有内容都包装在子外壳中并通过管道传输到最后一个命令中,这似乎也无关紧要。
我对这种行为深感困惑。
...由于阻塞读取和写入以及 while 循环并不总是产生输出的事实,在链中存在某种 I/O 死锁。但是,另一方面,我以前做过很多次这种事情,没有问题。另外,如果那样的话,while循环和下一个命令之间不就存在问题了吗?所以我很困惑。如果没有其他人可以复制,将提供 bash 版本信息。
这行代码的重点是打印电池百分比的每个变化,但只打印新的电池电量。它使用轮询。我想我可以通过简单地运行获得相同的行为
upower --monitor-detail | grep percentage | uniq
Run Code Online (Sandbox Code Playgroud)
但这是一次性的事情,我不打算在上面花费超过 5 秒的思考时间,直到上面开始失败。在这一点上,它变成了一个有趣的问题。另外,我不知道 monitor-detail 是否只是在幕后进行轮询(而且我没有运行 strace 来检查)。
编辑:显然,上面的--monitor-detail
版本也没有产生任何东西(或者,至少,它似乎。轮询/更新频率非常低,所以我可能等待的时间不够长。虽然我知道我等了足够长的时间原来的问题)。现在我非常非常困惑。我想我应该运行那个 strace ......
除了 Marco d'Itri 的回答之外,并非每个工具都支持自定义缓冲。如果您正在运行的工具没有,或者如果您想使用自定义缓冲区大小运行它,您可以使用stdbuf
覆盖工具的缓冲行为;在这种情况下,例如,强制输出为行缓冲:
while true ; do upower -d ; sleep 1 ; done | stdbuf -oL grep 'percentage' | uniq
Run Code Online (Sandbox Code Playgroud)
强制输出无缓冲:
while true ; do upower -d ; sleep 1 ; done | stdbuf -o0 grep 'percentage' | uniq
Run Code Online (Sandbox Code Playgroud)
要强制输出以 512 B 的块进行缓冲:
while true ; do upower -d ; sleep 1 ; done | stdbuf -o512 grep 'percentage' | uniq
Run Code Online (Sandbox Code Playgroud)
您可以添加 K、M、G、[...] 以指定以 KB、MB、GB、[...] 为单位的输出:
while true ; do upower -d ; sleep 1 ; done | stdbuf -o512K grep 'percentage' | uniq
Run Code Online (Sandbox Code Playgroud)