tee stdout 和 stderr 来分隔文件,同时将它们保留在各自的流上

2024-03-13

我正在尝试编写一个脚本,其本质上充当(非交互式)命令创建的所有输出的直通日志,而不影响命令到其他进程的输出。也就是说,stdout 和 stderr 应该看起来像没有运行过我的命令一样。

为此,我尝试将 stdout 和 stderr 分别重定向到两个不同的 tee,每个 tee 对应一个不同的文件,然后重新组合它们,以便它们仍然分别出现在 stdout 和 stderr 上。我看到了很多有关发球台和重定向的其他问题,并尝试了从这些问题中收集到的一些答案,但似乎没有一个能够将流拆分为单独的发球台然后正确地重新组合它们。

我的尝试成功地将输出分割成正确的文件,但流没有正确保留实际的 stdout/stderr 输出。我在更复杂的设置中看到了这一点,因此我创建了简化的命令,其中我将数据回显到 stdout 或 stderr 作为我的“命令”,如下所示。

以下是我尝试过的一些事情:

{ command | tee ~/tee.txt; } 2>&1 | { tee ~/tee2.txt 1>&2; }

运行我的简单测试我看到:

$ { { { echo "test" 1>&2; } | tee ~/tee.txt; } 2>&1 | { tee ~/tee2.txt 1>&2; } } > /dev/null
test
$ { { { echo "test" 1>&2; } | tee ~/tee.txt; } 2>&1 | { tee ~/tee2.txt 1>&2; } } 2> /dev/null
$

好的,这正如我所期望的那样。我正在回显到 stderr,因此当我将最终的 stderr 重定向到 /dev/null 时,我希望看不到任何内容,而当我仅重定向 stdout 时,我预计看不到任何内容。

$ { { { echo "test";  } | tee ~/tee.txt; } 2>&1 | { tee ~/tee2.txt 1>&2; } } > /dev/null
test
$ { { { echo "test";  } | tee ~/tee.txt; } 2>&1 | { tee ~/tee2.txt 1>&2; } } 2> /dev/null
$

这是倒退!我的命令仅将数据发送到标准输出,因此当我将最终标准输出重定向到 null 时,我希望看不到任何内容。但事实恰恰相反。

这是我尝试的第二个命令,它有点复杂:

{ command 2>&3 | tee ~/tee.txt; } 3>&1 1>&2 | { tee /home/michael/tee2.txt 1>&2; }

不幸的是,我看到了与以前相同的行为。

我真的看不出我做错了什么,但似乎标准输出正在以某种方式被破坏。在第一个命令的情况下,我怀疑这是因为我结合了 stdout 和 stderr (2>&1)在我将它通过管道传输到第二个 tee 之前,但如果是这种情况,我希望在 tee2.txt 文件中看到 stdout 和 stderr,但我没有 - 我只看到 stderr!在第二个命令的情况下,阅读我为该命令改编的答案后的印象是,描述符正在交换以避免此问题,但显然仍然出现问题。

编辑:我有另一个想法,也许第二个命令失败,因为我正在重定向1>&2这就是从第一个发球台杀死标准输出。所以我尝试将其重定向1>&4然后最后将其重定向回标准输出:

{ command 2>&3 | tee ~/tee.txt; } 3>&1 1>&4 | { tee /home/michael/tee2.txt 1>&2 4>&1; }

但现在我得到:

-bash: 4: Bad file descriptor

我还尝试将描述符 2 重定向回最终 T 恤中的描述符 1:

{ command 2>&3 | tee ~/tee.txt; } 3>&1 1>&2 | { tee /home/michael/tee2.txt 1>&2 2>&1; }

and:

{ command 2>&3 | tee ~/tee.txt; } 3>&1 1>&2 | { tee /home/michael/tee2.txt 1>&2; } 2>&1

基于流程替代的解决方案很简单,尽管并不像您想象的那么简单。我的第一次尝试似乎应该有效

{ echo stdout; echo stderr >&2; } > >( tee ~/stdout.txt ) \
                                 2> >( tee ~/stderr.txt )

然而,它并没有完全按照预期工作bash因为第二个tee从原始命令继承其标准输出(因此它转到first tee) 而不是来自调用 shell。目前尚不清楚这是否应该被视为一个错误bash.

可以通过将输出重定向分成两个单独的命令来修复它:

{ { echo stdout; echo stderr >&2; } > >(tee stdout.txt ); } \
                                   2> >(tee stderr.txt )

更新:第二次tee实际上应该是tee stderr.txt >&2以便从标准错误读取的内容被打印回标准错误。

现在,标准错误的重定向发生在没有重定向其标准输出的命令中,因此它以预期的方式工作。外部复合命令将其标准错误重定向到外部tee,其标准输出留在终端上。这inner复合命令从外部继承其标准错误(因此它也转到外部tee, while its标准输出被重定向到内部tee.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

tee stdout 和 stderr 来分隔文件,同时将它们保留在各自的流上 的相关文章

随机推荐

  • 如何使用C断言让代码更安全?

    阅读杂项 与SDL开发相关的教程我发现了两个不同的例子 做同样的事情 但以不同的方式 我想知道从代码 安全性 和可维护性的角度来看 您认为这两者中哪一个是正确的 在第一个示例中 程序员根本没有使用断言 但代码看起来不错 至少在我看来 int
  • 零 SQL 死锁设计 - 有编码模式吗?

    我在 MS SQL Server 2005 之上运行的 NET 2 0 Web 应用程序上遇到了非常罕见但烦人的 SQL 死锁 过去 我们一直以非常经验的方式处理 SQL 死锁 基本上是调整查询直到它起作用 然而 我发现这种方法非常不令人满
  • .net 中的固定块

    我对何时需要固定块有点困惑 我有一个例子 它给了我一个矛盾的场景 如下 enum RoomType Economy Buisness Executive Deluxe struct HotelRoom public int Number p
  • maven生成pom文件

    我使用maven 3 0 3并尝试为第三方jar生成pom 如下所示 mvn install 安装文件 Dfile cobra jar DgroupId com cobra DartifactId cobra Dversion 0 98 4
  • 动态更改函数的返回类型

    我正在编写一个具有返回类型的函数 该函数将根据我们传递的列动态更改 在下面的代码中 我传递列值 列数据类型 但我在运行代码时遇到错误 带有返回值的 RETURN 语句不能在此使用 语境 如果这是不可能的 那么如何动态更改返回类型 请提出解决
  • 如何估计在 z3 for SMT 中解决 SAT 部分所花费的时间?

    我已经使用探查器 gprof statshere http www ccs neu edu jaideep example2 stats包括调用图 并试图将所花费的时间分为两类 I SAT 求解部分 包括 纯 布尔传播和 纯 布尔冲突子句检
  • 'T'、'f'、'E'、'e'、'→' 在 dart/flutter 文档中代表什么?

    我正在学习颤振 但我不明白这些字母的含义 map
  • 安装 SQL Server 2016 时出现错误代码 0x84BB0001

    操作系统 Windows Server 2012 R2 当尝试在已运行 SQL 2012 的服务器上安装 SQL Server 2016 时 我收到 0x84BB0001 这会阻止我的数据库引擎服务正确安装 没有运行任何防病毒软件 我已删除
  • Webview 显示错误“未找到类“android.webkit.RenderProcessGoneDetail”

    我的平板电脑 Android 版本是 7 0 Chrome 版本是 62 0 3202 84 第一次运行我的 webview 应用程序时 调试窗口显示 没有找到类 android webkit RenderProcessGoneDetail
  • 对 Ruby on Rails 代码进行编码?

    是否有任何应用程序可以让我对 Ruby on Rails 代码进行编码 以便其他人无法读取它 我计划出售一些小型应用程序 但我真的不希望每个人都知道我的代码 Thanks 我在野外见过的唯一例子是 ThoughtWorks 的 Mingle
  • 如何从 RethinkDB 文档中删除键?

    我正在尝试从 RethinkDB 文档中删除一个键 我的方法 没有用 r db db table user replace function row delete row key return row 其他方法 r db db table
  • exe运行涉及的步骤

    Question 当我们运行一个exe 假设通过双击 时 在它实际开始执行之前所有时间都花在哪里 a 将exe加载到内存中 b c 问题背景 我正在分析应用程序 App exe 的执行情况并尝试提高其性能 我有一个测试 它的作用如下 开始时
  • Rust 0.13 中大型固定大小数组的堆栈溢出

    我希望与 Rust 专家验证这个简单的 Rust 程序 Linux x86 64 系统上的 rustc 0 13 0 nightly the runtime error is task
  • 如何在gridview中动态添加的文本框上触发textboxchanged事件

    在我的项目中 我可以在gridview中动态添加n个文本框 我的问题是 如果用户更改 gridview 任何行中任何文本框的文本 我想触发 textboxchanged 事件 HTML 代码
  • numpy:将 (n,) 数组转换为 (n, 1) 数组的语法/习惯用法?

    我想投射一个 numpyndarray形状物体 n 变成具有形状 n 1 我想出的最好的方法是推出我自己的 to col 函数 def to col a return a reshape a size 1 但我很难相信这样一个普遍存在的操作
  • Eclipse - Builder 到底是什么?

    我不明白CDT中的构建器到底是什么 与 C C Build 内容有什么关系 我在 C C Build 配置中设置了SCons 它确实有效 我做了两个配置 发布和调试 并且启动了我的 SCons 脚本 但当我现在尝试调试时 我正在研究这些 B
  • 在 for 循环中动态创建文本框

    我试图动态创建一个表格并将文本框放入其中 在下面的代码中 我试图为每个 k 创建一个具有不同名称的文本框 但文本框中仅显示 k 的最后一个值 我想知道如何为文本框命名以便显示所有内容 for int k 0 k lt tblCols k T
  • 在c#中调用带参数的存储过程

    我能够在程序中删除 插入和更新 并且尝试通过从数据库调用创建的存储过程来执行插入 我制作的这个按钮插件效果很好 private void btnAdd Click object sender EventArgs e SqlConnectio
  • 处理 Airflow DAG 随着时间的变化(DAG 版本控制)

    我们有相对复杂的动态 DAG 作为 ETL 的一部分 DAG 包含数百个转换 它是基于一组 yaml 文件以编程方式创建的 它随着时间的推移而发生变化 添加新任务 任务执行的查询发生变化 甚至任务之间的关系也发生变化 我知道每次以这种方式更
  • tee stdout 和 stderr 来分隔文件,同时将它们保留在各自的流上

    我正在尝试编写一个脚本 其本质上充当 非交互式 命令创建的所有输出的直通日志 而不影响命令到其他进程的输出 也就是说 stdout 和 stderr 应该看起来像没有运行过我的命令一样 为此 我尝试将 stdout 和 stderr 分别重