当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在脚本本身内重定向整个shell脚本的输出?》经验,为你挑选了4个好方法。

是否可以将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定期实用程序运行的脚本执行此操作.它是日常运行的一部分,我通常不会每天都看到电子邮件,所以我没有发送它.但是,如果这个特定脚本中的某些内容失败,那对我来说很重要,我希望能够捕获并通过电子邮件发送这部分日常工作的输出.

更新: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

Joshua.. 161

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

将stdout发送到文件

exec > file

与stderr

exec > file                                                                      
exec 2>&1

将stdout和stderr追加到文件中

exec >> file
exec 2>&1

正如Jonathan Leffler 在评论中提到的那样:

exec有两个独立的工作.第一个是用新程序替换当前正在执行的shell(脚本).另一种是改变当前shell中的I/O重定向.这是因为没有争论exec.



1> Joshua..:

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

将stdout发送到文件

exec > file

与stderr

exec > file                                                                      
exec 2>&1

将stdout和stderr追加到文件中

exec >> file
exec 2>&1

正如Jonathan Leffler 在评论中提到的那样:

exec有两个独立的工作.第一个是用新程序替换当前正在执行的shell(脚本).另一种是改变当前shell中的I/O重定向.这是因为没有争论exec.


`exec >>(tee -a"logs/logdata.log")2>&1`在屏幕上打印日志并将它们写入文件
我说也加上2>&1到最后,这样stderr也被抓住了.:-)
你把它们放在哪里?在脚本的顶部?
@JohnRed:`exec`有两个独立的工作.一种是用另一个命令替换当前脚本,使用相同的过程 - 将另一个命令指定为`exec`的参数(并且可以调整I/O重定向).另一项工作是更改当前shell脚本中的I/O重定向而不替换它.这种表示法的特点是没有命令作为`exec`的参数.此答案中的符号是"仅I/O"变体 - 它只更改重定向,而不替换正在运行的脚本.(`set`命令同样是多用途的.)
使用此解决方案,还必须重置脚本退出的重定向.Jonathan Leffler的下一个答案在这个意义上更"失败".

2> Jonathan Lef..:

将问题解决为更新.

#...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以及你所展示的重定向,但对于那些必须稍后维护脚本的人来说,如果你按照上面的说明调整重定向代码的范围,通常会更容易理解.


我不得不做一些谷歌搜索来了解这是真的在做什么,所以我想分享.花括号成为["代码块"](http://www.tldp.org/LDP/abs/html/special-chars.html#CODEBLOCKREF),实际上,它创建了一个_anonymous function_.然后可以重定向代码块中的所有输出(参见**示例3-2**来自该链接).另请注意,花括号_do not_启动[subshel​​l](http://www.tldp.org/LDP/abs/html/subshel​​ls.html),但类似[I/O重定向](http://www.tldp) .org/LDP/abs/html/ioredirintro.html)_can_使用括号完成子壳.
这比保存原始描述符并在以后恢复它们要清楚得多.
我比其他人更喜欢这个解决方案.即使是对I/O重定向只有最基本了解的人也能理解正在发生的事情.另外,它更冗长.而且,作为一个Pythoner,我喜欢冗长.

3> dbguy..:

您可以使整个脚本成为这样的函数:

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

或者,您可以在每次运行时将所有内容记录到logfile中,并通过简单地执行以下操作将其输出到stdout:

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



4> Eyal leshem..:

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

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

例如,以下代码将“ walla1”和“ walla2”打印到日志文件(a.txt),将“ walla3”打印到标准输出,将“ 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

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有