如何将Shell脚本的标准输出和标准错误输出打印到文件和控制台?

4
在bash脚本中,我使用以下语法将脚本的所有内容打印到文件$file$sec_file中。
我们在我们的Linux RHEL 7.8服务器上运行脚本。
exec > >(tee -a "$file" >>"$sec_file") 2>&1

当bash脚本完成后,我们将在两个文件中得到每行bash脚本的stdout/stderr内容。

现在我们还想将stdout/stderr打印到控制台而不仅仅是文件中。

我会感激任何建议。

脚本示例:

# more  /tmp/script.bash

#!/bin/bash

file=/tmp/file.txt
sec_file=/tmp/sec_file.txt

exec > >(tee -a "$file" >>"$sec_file") 2>&1

echo "hello world , we are very happy to stay here "

运行脚本的示例:

/tmp/script.bash

<--  no output from the script -->

# more /tmp/file.txt
hello world , we are very happy to stay here
# more /tmp/sec_file.txt
hello world , we are very happy to stay here

以下是应该作为期望输出的示例。

/tmp/script.bash
hello world , we are very happy to stay here

# more /tmp/file.txt
hello world , we are very happy to stay here
# more /tmp/sec_file.txt
hello world , we are very happy to stay here

只是为了明确,您希望在执行后这两个文件包含完全相同的文本吗? - toydarian
是的,两个文件都应该捕获stdout和stderr。 - jessica
2个回答

0

我认为最简单的方法就是将多个文件作为参数添加到tee中,就像这样:

% python3 -c 'import sys; print("to stdout"); print("to stderr", file=sys.stderr)' 2>&1 | tee -a /tmp/file.txt /tmp/file_sec.txt
to stdout
to stderr
% cat /tmp/file.txt 
to stdout
to stderr
% cat /tmp/file_sec.txt 
to stdout
to stderr

你的脚本应该是这样的:

#!/bin/bash

file=/tmp/file.txt
sec_file=/tmp/sec_file.txt

exec > >(tee -a "$file" "$sec_file") 2>&1

echo "hello world , we are very happy to stay here "

3
不需要额外的 "tee" 命令 - echo "ok" | tee -a file1 file2 filen 可以正常工作。 - bob dylan
没错,最简单的解决方案往往被轻易地忽略了... 我更新了答案。 - toydarian
我的意思是,你举了Python的例子,但我们在这里讨论的是Bash。其次,我想避免通过在脚本中添加管道和tee来解决问题,解决方案应该在脚本内部实现,而不是通过添加管道与脚本一起使用。 - jessica
我已经更新了我的答案,并为您提供了一个示例。Python只是一个“懒惰的演示”而已。 - toydarian
根据您的更新,我发现有一点问题,脚本没有结束,就好像脚本挂起了,尽管它仍在工作。 - jessica
显示剩余4条评论

0
我建议将控制台的事情写到一个新的输出通道中:
#!/bin/bash
file=file.txt
sec_file=sec_file.txt

exec 4>&1 > >(tee -a "$file" >>"$sec_file") 2>&1

echo "stdout"
echo "stderr" >&2
echo "to the console" >&4

输出:

me@pc:~/⟫ ./script.sh 
to the console
me@pc:~/⟫ cat file.txt 
stdout
stderr
me@pc:~/⟫ cat sec_file.txt 
stdout
stderr

如果你想,你可以这样做,甚至可以使用>&5再次写入到stderr:

exec 4>&1 5>&1 > >(tee -a "$file" >>"$sec_file") 2>&1
echo "stderr to console" >&5

编辑:将&3更改为&4,因为&3有时用于stdin。

但也许现在是重新考虑你正在做的事情并保留&1标准输出和&2标准错误,并使用&4&5来写入文件的时候了?

exec 4> >(tee -a "$file" >>"$sec_file") 5>&1

这确实要求您将应该出现在文件中的所有行添加到前缀 >&4 2>&5


我尝试了,但是它没有在控制台上打印。 - jessica
我在GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)上尝试了一下,这似乎是您正在使用的相同版本,对于我来说,我的第一个片段有效。您是否注意到我稍微更改了exec行?您复制整个脚本还是只复制了部分内容? - Veda

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