代码之家  ›  专栏  ›  技术社区  ›  Steve Madsen

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

  •  149
  • Steve Madsen  · 技术社区  · 17 年前

    重定向单个命令的输出很容易,但我希望更像这样:

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

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

    # 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
    
    5 回复  |  直到 5 年前
        1
  •  210
  •   Jonathan Leffler    7 年前

    根据最新情况解决问题。

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

    是的,这可以更加精确;如果你想狡辩,请告诉我。 )

    您是对的,您可以通过显示的重定向来保留原始的stdout和stderr,但是对于以后需要维护脚本的人员来说,如果您按照上面所示的方式定义重定向代码的范围,则通常更容易理解发生了什么。

    Grouping Commands I/O Redirection Compound Commands I/O Redirection . Bash有一些额外的符号,但在其他方面类似于posixshell规范。

        2
  •  206
  •   Joachim Sauer    7 年前

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

    将标准输出发送到文件

    exec > file
    

    exec > file                                                                      
    exec 2>&1
    

    将stdout和stderr都附加到文件中

    exec >> file
    exec 2>&1
    

    Jonathan Leffler mentioned in his comment :

    exec 他有两份不同的工作。第一个是用新程序替换当前正在执行的shell(脚本)。另一个是更改当前shell中的I/O重定向。这一点的特点是没有任何理由支持 执行官

        3
  •  39
  •   Daniel Serodio    9 年前

    您可以使整个脚本成为如下函数:

    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
    

    或者,您可以在每次运行时将所有内容都记录到日志文件中,并通过执行以下操作将其输出到标准输出:

    # log everything, but also output to stdout
    main_function 2>&1 | tee -a /var/log/my_uber_script.log
    
        4
  •  7
  •   Jonathan Leffler    9 年前

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

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

    a.txt )“walla3”到标准件,“walla4”到标准件。

    #!/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
    
        5
  •  4
  •   Thiem Nguyen    13 年前
    [ -t <&0 ] || exec >> test.log