如何在脚本本身内重定向整个 shell 脚本的输出?
是否可以将 Bourne 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 定期实用程序运行的脚本执行此操作。 这是日常运行的一部分,我通常不喜欢每天在电子邮件中看到它,所以我没有发送它。 但是,如果这个特定脚本中的某些内容失败,这对我来说很重要,我希望能够捕获并通过电子邮件发送这部分日常工作的输出。
更新:约书亚的答案是正确的,但我也想保存和恢复整个脚本的标准输出和标准错误,这样做是这样的:
# 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
Is it possible to redirect all of the output of a Bourne shell script to somewhere, but with shell commands inside the script itself?
Redirecting the output of a single command is easy, but I want something more like this:
#!/bin/sh
if [ ! -t 0 ]; then
# redirect all of my output to a file here
fi
# rest of script...
Meaning: if the script is run non-interactively (for example, cron), save off the output of everything to a file. If run interactively from a shell, let the output go to stdout as usual.
I want to do this for a script normally run by the FreeBSD periodic utility. It's part of the daily run, which I don't normally care to see every day in email, so I don't have it sent. However, if something inside this one particular script fails, that's important to me and I'd like to be able to capture and email the output of this one part of the daily jobs.
Update: Joshua's answer is spot-on, but I also wanted to save and restore stdout and stderr around the entire script, which is done like this:
# 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
解决更新后的问题。
大括号“{ ... }”提供 I/O 重定向单元。 大括号必须出现在命令可能出现的位置 - 简单地说,在行的开头或分号之后。 (是的,这可以做得更精确;如果您想狡辩,请告诉我。)
您是对的,您可以使用您显示的重定向来保留原始的 stdout 和 stderr ,但通常是如果您按如上所示确定重定向代码的范围,对于稍后必须维护脚本以了解发生的情况的人员来说会更简单。
Bash 手册的相关部分是 分组命令 和I/O 重定向。 POSIX shell 规范的相关部分是 复合命令 和 < a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07" rel="noreferrer">I/O 重定向。 Bash 有一些额外的符号,但在其他方面与 POSIX shell 规范类似。
Addressing the question as updated.
The braces '{ ... }' provide a unit of I/O redirection. The braces must appear where a command could appear - simplistically, at the start of a line or after a semi-colon. (Yes, that can be made more precise; if you want to quibble, let me know.)
You are right that you can preserve the original stdout and stderr with the redirections you showed, but it is usually simpler for the people who have to maintain the script later to understand what's going on if you scope the redirected code as shown above.
The relevant sections of the Bash manual are Grouping Commands and I/O Redirection. The relevant sections of the POSIX shell specification are Compound Commands and I/O Redirection. Bash has some extra notations, but is otherwise similar to the POSIX shell specification.
通常我们会将其中之一放置在脚本的顶部或附近。 解析命令行的脚本将在解析后进行重定向。
文件
将 stdout 发送到带有 stderr 的
将 stdout 和 stderr 附加到文件
As Jonathan Leffler 在他的评论中提到:
exec
有两个独立的工作。 第一个是用新程序替换当前正在执行的 shell(脚本)。 另一个是更改当前 shell 中的 I/O 重定向。 其特点是exec
没有参数。Typically we would place one of these at or near the top of the script. Scripts that parse their command lines would do the redirection after parsing.
Send stdout to a file
with stderr
append both stdout and stderr to file
As Jonathan Leffler mentioned in his comment:
exec
has two separate jobs. The first one is to replace the currently executing shell (script) with a new program. The other is changing the I/O redirections in the current shell. This is distinguished by having no argument toexec
.您可以使整个脚本成为这样的函数:
然后在脚本的末尾添加以下内容:
或者,您可以在每次运行时将所有内容记录到日志文件中,然后仍然将其输出到标准输出,只需执行以下操作:
You can make the whole script a function like this:
then at the end of the script have this:
Alternatively, you may log everything into logfile each run and still output it to stdout by simply doing:
为了保存原始的stdout和stderr,您可以使用:
例如,以下代码将打印“walla1”和“walla2”到日志文件(
a.txt
),“walla3”到stdout,“ walla4" 到 stderr。For saving the original stdout and stderr you can use:
For example, the following code will print "walla1" and "walla2" to the log file (
a.txt
), "walla3" to stdout, "walla4" to stderr.我终于知道该怎么做了。 我不仅想将输出保存到文件中,还想了解 bash 脚本是否成功运行!
我将 bash 命令包装在一个函数中,然后调用该函数
main_function
并将 tee 输出输出到文件中。 之后,我使用if [ $? -eq 0]
。I finally figured out how to do it. I wanted to not just save the output to a file but also, find out if the bash script ran successfully or not!
I've wrapped the bash commands inside a function and then called the function
main_function
with a tee output to a file. Afterwards, I've captured the output usingif [ $? -eq 0 ]
.