避免在 bash 脚本中为命令组(花括号)进行输出缓冲

Tho*_*hel 4 bash pipe shell-script buffer

我有一个 bash 脚本,其中包含花括号中的一组命令{ ... }。该组包含一些初始echo命令和一个循环。在每次迭代中,循环执行各种缓慢的命令(基本上是curl一些额外的解析)。每次迭代都很慢(因为网络交互),但它打印了一行(python 代码);据我所知,命令本身不应该有缓冲问题,因为它们终止了工作并离开。

整组命令都通过管道传送到python -u(我也尝试使用tail -f以进行检查)并且显然整个循环是在python -uor读取任何内容之前执行的tail -f

我知道如何使用各种工具取消缓冲(如果可能)一个命令,stdbuf但我认为它在这里没有帮助,因为看起来问题来自命令分组而不是来自这样或那样的命令。

任何提示?

Tom*_*ych 5

(请注意未来的读者:这里恼怒的语气不是针对这个问题,而是针对我在试图回答这个问题时犯的错误以及它们所带来的多次编辑。)

哦,看在怜悯的份上。问题出在tail -f. 这工作得很好:

#!/bin/bash
printf 'hi\n'
{
    for i in 1 2 3 4; do
        sleep 0.5
        /bin/echo $i
    done;
} | cat
printf 'bye\n'
Run Code Online (Sandbox Code Playgroud)

这不是管道,也不是小组。它是tail。就像在追逐我们自己的尾巴一样!

所以,tail -f失败是因为它由于某种原因没有立即输出。不知道为什么python -u会失败,但我认为脚本中没有任何内容。也许试试unbuffer吧。cat至少使用 尝试您的脚本,并验证在这种情况下它是无缓冲的。


早先失败的尝试故意留在这里,以便未来的读者可以理解这些评论。

此脚本展示了您遇到的相同类型的缓冲问题:

#!/bin/bash
printf 'hi\n'
{
    for i in 1 2 3 4; do
    sleep 0.5
    printf '%s\n' $i
    done;
} | tail -f
printf 'bye\n'
Run Code Online (Sandbox Code Playgroud)

这个没有。组内的输出被重定向到 stderr,然后来自整个组的 stderr 通过管道传输到命令。因为它是 stderr,所以它是无缓冲的。

#!/bin/bash
printf 'hi\n'
{
    for i in 1 2 3 4; do
    sleep 0.5
    printf '%s\n' $i 1>&2
    done;
} |& tail -f
printf 'bye\n'
Run Code Online (Sandbox Code Playgroud)

改编自王宏勤在这个问题中的回答。困难在于找到一种使用大括号而不是显式命令来解除管道缓冲的方法。不得不摆弄一段时间才能使重定向正常工作。