永久重定向stdout和stderr到文件,但仍然打印它们

3
通过以下操作(1):
 exec >> log_file
 exec 2>&1
 ls

stdoutstderr将永久重定向到下一条命令,但不再在终端上显示。这里,ls输出将保存在log_file中,但不会在终端上显示。

通过执行以下操作(2):

command | tee log_file

command的输出结果既会被记录到log_file中,也会在终端上打印出来,但这只适用于command命令,而不适用于后续的命令,这是方法1。

如何像方法1一样永久重定向给定终端的stdoutstderr输出到文件中,并保持在终端实例上打印stdoutstderr,就像方法2一样?

2个回答

4

我目前在我的脚本中使用以下代码:

exec > >(tee -a "${FILE_Log}" )
exec 2> >(tee -a "${FILE_Log}" >&2)

基本上,您告诉bash将输出(包括stdout和stderr)发送到tee的stdin,并且由于tee在子shell(括号内)中运行,因此它将与您的脚本一样长寿。
将其放在靠近顶部的位置,然后所有命令输出、echo、print和printf都将被记录。
这样可以避免创建LOG()函数并不断将命令传输到tee的麻烦。
希望这有所帮助!

谢谢您的回答,这非常接近我所需要的!当您向脚本发送信号时,它会导致Bash崩溃吗? - Thomas Kostas
我不相信它会这样做。我还没有测试过向它发送信号。我相信它会继续运行。 - Hickory420
对我来说,不幸的是这导致了一个 Bash 崩溃。 - Thomas Kostas
你向脚本传递了什么信号? - Hickory420
我发送了一个SIGINT信号。 - Thomas Kostas
这种方法不幸地不太可靠:当前脚本将完成并退出,并返回到用户提示符(或继续在某个更高级别的调用脚本中),在tee完成写入日志文件和完成写入正常stdout和stderr之前。不良后果包括:(1)提示符出现在用户终端的最后几行输出之前,(2)期望日志文件完整的后续命令将看不到正确的内容。 - Don Hatch

0

使用tee和重定向组合:

(exec 2>&1) | tee file.txt

这是一个例子

[root@box ~]# (ll 2>&1) | tee tmp.txt
total 4
-rw-------. 1 root root 1007 Apr 26  2017 anaconda-ks.cfg
[root@box ~]# cat tmp.txt
total 4
-rw-------. 1 root root 1007 Apr 26  2017 anaconda-ks.cfg

命令放在括号里的原因是为了保持打印顺序,因为stdout被缓冲。它会导致ll命令在子shell中执行,然后以顺序返回stdout + stderr的输出。

谢谢您的回答,但很遗憾这并不起作用...这个例子只适用于"ll"命令,而不是后面使用的命令。 这个解决方案根本不起作用。 - Thomas Kostas
echo,ls,任何命令,但在执行它们之前做(exec 2>&1)| tee logfile不会将它们的输出放入logfile中。 - Thomas Kostas
@Thomas Kostas,这个方向不是直接与上面的问题相关的,但我想你可以在tee命令后添加-atee -a logfile可以在每次执行时将输出添加到logfile中。 - Daein Park
@ThomasKostas 尝试不使用括号执行它,因为 exec 会打开自己的子 shell(我以为你只是用它作为一个命令的通用名称..) - Chen A.
这是一个非常令人困惑的答案。问题使用 exec 的字面意思,但看起来你已经重新定义它来表示其他东西(一个通用命令的占位符?)即使有人弄清楚了这一点,这也不是问题的答案,问题是如何控制 所有 后续命令的输出,而不仅仅是一个命令。 - Don Hatch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接