我正在尝试编写一个脚本,其本质上充当(非交互式)命令创建的所有输出的直通日志,而不影响命令到其他进程的输出。也就是说,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