首页 > 解决方案 > 将 stdout 和 stderr 重定向到文件,将 stderr 重定向到屏幕,同时保留输出顺序

问题描述

我想将 stdout 和 stderr 重定向到一个文件,同时保留输出顺序,但同时也将 stderr 显示到屏幕上。我看到很多问题都在讨论它:

但他们似乎都没有做我想做的事或保持秩序。

我的测试脚本:

#!/bin/bash

echo "1: good" >&1
echo "2: error" >&2
echo "3: error" >&2
echo "4: good" >&1
echo "5: error" >&2
echo "6: good" >&1
echo "7: error" >&2
echo "8: good" >&1
echo "9: error" >&2

到目前为止我所拥有的:

$ ./test.sh 2>&1 > output.log

标签: bashstdoutstderrio-redirection

解决方案


标准 UNIX 语义不允许这样做;仅使用内置在 bash 中或在 POSIX 中指定的工具无法可靠地完成它。

只有当它们发生在同一个目的地时,写入才具有相互关联的保证顺序。一旦您将 stdout 和 stderr 重定向到不同的目的地,操作系统就不再提供对它们执行的写入顺序的保证;当这些写入是针对一个单独的进程(例如tee)时,该进程必须读取内容并执行其自己的进一步写入,受操作系统级调度的影响。

可以使用操作系统提供(或可用于)您的操作系统提供的系统调用级跟踪工具来生成系统调用的绝对顺序,从而生成明确排序的输出;在不丢失排序的情况下单独重定向和重新组合 stderr/stdout的答案中给出了一个示例。

但是,使用 bash 本身,您只能控制连接子进程的文件描述符的位置,而不是如何缓冲和刷新写入这些描述符的内容,因此根本没有足够的控制来使您要求的内容成为可能写入可能会重新排序。


推荐阅读