将 stderr 发送到管道中的不同接收器

将 stderr 发送到管道中的不同接收器

现在我有这个:

 echo "$run_test" | bash 2>&1 | prepend "r2g-test:" "yellow";

其作用是在 stdout/stderr 的每一行前面添加“r2g-test:”。因为我将 stderr 发送到 stdout,所以prepend程序不知道其中的区别,因为它都是标准输入。

有什么方法可以将 stderr 发送到不同的prepend实例吗tee

也许是这样的?

 echo "$run_test" | bash 2> $(prepend 'r2g-test:' 'red') | prepend 'r2g-test:' 'yellow';

通过进程替换,这可能会起作用:

bash 2> >(prepend 'r2g-test:' 'red')

但到目前为止,stderr 从未出现在终端中

答案1

首先,让我们创建一个run_test生成 std​​out 和 stderr 的程序:

$ run_test() { while sleep 0.2; do echo "Out $((++c))"; echo "err$c">&2; done; }

现在,让我们将 stdout 和 stderr 发送到不同的过滤器。由于我没有prepend安装,我将用于sed相同的目的:

$ exec 3>&2; { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

怎么运行的

  • exec 3>&2

    这将创建文件描述符 3 作为 stderr 的副本。

  • run_test | sed 's/^/stdout: /'

    这将运行run_test并添加stdout:到标准输出的开头。

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3

    2>&将 stderr 重定向到 stdout,以便 stderr 将进入下一个管道。 1>&3将 stdout 重定向到 stderr,以便它显示在终端上。

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'

    最后一个管道捕获 run_test 的 stderr(现在是 stdout)并添加stderr:到它的前面。

使用进程替换

$ run_test > >(sed 's/^/stdout: /') 2> >(stdbuf -oL sed 's/^/stderr: /' >&2)
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

以上使用的stdbuf是 Linux 上的标准。对于其他操作系统,需要寻找类似的命令。

相关内容