如何在脚本本身重定向整个shell脚本的输出?

是否有可能重定向一个伯恩shell脚本的所有输出到某个地方,但在脚本本身的shell命令?

重定向单个命令的输出很容易,但我想要的东西更像这样:

#!/bin/sh
if [ ! -t 0 ]; then
# redirect all of my output to a file here
fi


# rest of script...

含义:如果脚本以非交互方式运行(例如,cron),则将所有输出保存到一个文件中。如果从shell以交互方式运行,则像往常一样让输出进入stdout。

我想为通常由FreeBSD周期实用程序运行的脚本执行此操作。这是日常工作的一部分,我通常不愿意在每天的电子邮件中看到,所以我没有发送它。但是,如果这个特定脚本中的某些内容失败了,这对我来说很重要,我希望能够捕获并通过电子邮件发送日常工作的这一部分的输出。

更新:Joshua的答案是正确的,但我也想保存和恢复整个脚本周围的stdout和stderr,这是这样做的:

# save stdout and stderr to file
# descriptors 3 and 4,
# then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1


# ...


# restore stdout and stderr
exec 1>&3 2>&4
224306 次浏览

通常,我们会将其中一个放在脚本的顶部或顶部附近。解析命令行的脚本将在解析后执行重定向。

发送标准输出到文件

exec > file

与stderr

exec > file
exec 2>&1

将stdout和stderr附加到文件中

exec >> file
exec 2>&1

As Jonathan Leffler 在他的评论中提到:

exec有两个独立的任务。第一种方法是用一个新程序替换当前正在执行的shell(脚本)。另一个是改变当前shell中的I/O重定向。它的区别在于没有exec的参数。

你可以把整个脚本变成这样一个函数:

main_function() {
do_things_here
}

然后在脚本的最后有这个:

if [ -z $TERM ]; then
# if not run via terminal, log everything into a log file
main_function 2>&1 >> /var/log/my_uber_script.log
else
# run via terminal, only output to screen
main_function
fi

或者,你可以在每次运行时将所有内容都记录到日志文件中,并仍然将其输出到stdout:

# log everything, but also output to stdout
main_function 2>&1 | tee -a /var/log/my_uber_script.log

解决问题的最新进展。

#...part of script without redirection...


{
#...part of script with redirection...
} > file1 2>file2 # ...and others as appropriate...


#...residue of script without redirection...

括号“{…} `提供一个I/O重定向单元。大括号必须出现在命令可能出现的地方——简单地说,在行首或分号之后。(是的,这可以更精确;如果你想狡辩,告诉我。)

您是对的,您可以保留原始的stdout和stderr以及您所显示的重定向,但是如果您如上所示对重定向的代码进行作用域,对于稍后必须维护脚本的人来说,理解发生了什么通常会更简单。

Bash手册的相关部分是分组命令I / O重定向。POSIX外壳规范的相关部分是复合命令I / O重定向。Bash有一些额外的符号,但在其他方面与POSIX外壳规范类似。

[ -t <&0 ] || exec >> test.log

要保存原始的stdout和stderr,您可以使用:

exec [fd number]<&1
exec [fd number]<&2

例如,下面的代码将“walla1”和“walla2”打印到日志文件(a.txt),“walla3”打印到stdout,“walla4”打印到stderr。

#!/bin/bash


exec 5<&1
exec 6<&2


exec 1> ~/a.txt 2>&1


echo "walla1"
echo "walla2" >&2
echo "walla3" >&5
echo "walla4" >&6

我终于知道该怎么做了。我不仅想要将输出保存到文件中,而且还想要确定bash脚本是否成功运行!

我将bash命令包装在一个函数中,然后调用函数main_function,并将tee输出到一个文件。然后,我使用if [ $? -eq 0 ]捕获输出。

#! /bin/sh -


main_function() {
python command.py
}


main_function > >(tee -a "/var/www/logs/output.txt") 2>&1


if [ $? -eq 0 ]
then
echo 'Success!'
else
echo 'Failure!'
fi