如何将标准输入 (stdin) 复制到 bash 脚本中的多个子进程?

How can I duplicate standard input (stdin) to multiple subprocesses in a bash script?

我想将 stdin 重定向到多个脚本,以便测试开发中的 git 挂钩,同时保留旧的挂钩。我知道我应该以某种方式使用 tee,但我不知道如何使用 bash 的基本 >< 和管道 | 重定向功能来做这个。此外,如何重定向脚本的标准输入?我不想使用 read,因为它一次只读取一行,我必须为每一行重新执行所有子进程。

您可以将 tee 与普通文件(可能是通过 mktemp 的临时文件)一起使用,然后 cat 将这些文件用于您的各种脚本。更直接地说,您可以用 mkfifo 创建的命名管道替换那些普通文件。但是您可以使用 Bash 强大的流程替换 >( cmd )<( cmd ) 功能在一个管道中完成此操作,以替换文件 tee 期望您的子流程。

对第一个 tee 使用 <&0 来获取脚本的标准输入。 编辑:正如 chepner 指出的那样,tee 默认继承 shell 的标准输入。

最终结果是这个包装脚本:

#!/bin/bash
set +o pipefail
tee >(testscipt >> testscript.out.log 2>> testscript.err.log) | oldscript

一些注意事项:

  • 使用 set +o pipefail 禁用 Bash 的 pipefail 功能(如果它之前已启用)。启用后,Bash 将从管道内报告错误。禁用时,它只会报告最后一个命令的错误,这就是我们在这里想让我们的测试脚本对包装器不可见的原因(我们希望它的行为就像它只是调用 oldscript 以避免中断。
  • 重定向测试脚本的标准输出,否则它将被转发到管道中的下一个命令,这可能不是您想要的。也可以重定向 stderr。
  • 任意数量的 tee 都可以像这样进行管道链接以复制您的输入 (但不要从初始的 <&0 标准输入重定向复制)(初始<&0已被删除)