【问题标题】:Conditionally redirect bash output, only print to cout and cerr on error有条件地重定向 bash 输出,仅在出错时打印到 cout 和 cerr
【发布时间】:2017-02-11 18:04:41
【问题描述】:

有没有简单的单行方式,或者简单的函数比如 bash 命令:

  1. 成功时默认将 cout 和 cerr 管道传输到文件
    • 换句话说,成功时不要打印到终端。
  2. 如果发生错误(即非零返回)
    • 捕获错误代码
    • 从 (1) 打印文件
    • 返回错误码
  3. 奖励:如果我可以重新启用默认打印 1 或 2 个字符,我会很高兴

动机:travis-ci 的总 log cout/cerr 大小限制为 4MB。这会在超出时终止构建,因此我只想打印实际错误,但 travis 也会在检测到错误时终止,就像set -e

【问题讨论】:

    标签: bash pipe stdout travis-ci stderr


    【解决方案1】:

    我认为你需要的是这样的:

    ls real_file.txt > /tmp/out.txt 2>&1 || echo $? && cat /tmp/out.txt
    ls non_existent.txt > /tmp/out.txt 2>&1 || echo $? && cat /tmp/out.txt
    

    补充:在OP反馈后:

    ls real_file.txt > /tmp/out.txt 2>&1 || (echo $? && cat /tmp/out.txt)
    ls non_existent.txt > /tmp/out.txt 2>&1 || (echo $? && cat /tmp/out.txt)
    

    【讨论】:

    • 这似乎不起作用,它不应该在成功时打印任何东西:○ echo "real_file_text" > real_file.txt○ cat real_file.txt > /tmp/out.txt 2>&1 || echo $? && cat /tmp/out.txt 输出:real_file_text
    • 现在我明白了。那么这应该可以解决问题: ls real_file.txt > /tmp/out.txt 2>&1 || (echo $? && cat /tmp/out.txt)
    【解决方案2】:

    http://mywiki.wooledge.org/BashFAQ/106 中所述,您可以对所有命令应用全局重定向。

    所以你可以像这样开始你的脚本:

    exec 3>&1 >log 2>&1
    

    使用此命令,新的 fd 3 将被分配给 screen,已存在的 fd1 将被发送到日志文件,stderr 也将被发送到日志文件。

    试一试(或查看我的测试here

    exec 3>&1 >log 2>&1
    ls nofile #This will raise an error on stderr
    echo "hello" #This would normally be printed on stdout / fd1
    echo "hello again" >&3 #This will go in fd3
    #Output:
    hello again
    
    $ cat log
    ls: cannot access nofile: No such file or directory                                                                                                                             
    hello
    

    ls 将失败(除非您有一个名为“nofile”的文件:))但错误消息将发送到 log gile。

    echo 将成功打印 "hello" ,但这将转到 fd1 ,这意味着再次记录到日志文件。

    最后一个回显被重定向到 fd3 = 你的真实屏幕,这是你在现实中看到的唯一消息。

    向前迈出一步,您可以使用 $? 捕获每个命令的结果? (如果要使用管道,则使用 bash PIPESTATUS 数组)。

    另一个测试:

    exec 3>&1 >log 2>&1
    ls nofile; ex=$?; 
    [[ "$ex" -ne 0 ]] && (echo "Oops, something gone wrong.Exit status = $ex" && cat log) >&3 
    
    #Output
    Oops, something gone wrong.Exit status = 2
    ls: cannot access nofile: No such file or directory
    

    另一种方式

    if ! ls nofile;then echo "something is wrong" >&3;fi
    

    如果 ls 失败,将在您的屏幕上打印“有问题”
    如果 ls 没有失败,将打印它的结果以进行日志记录,并且您在屏幕上什么也看不到。

    一般来说,使用这种方法,您可以始终将 stderr 和 stdout 重定向到一个文件,并且您可以通过在要打印结果的每个命令中应用 >&3 来选择性地在屏幕上打印消息你的屏幕。

    我不知道是否可以根据每个命令的退出状态进行自动重定向。这就是 stderr 的用途。打印错误。

    看来每条命令执行完后都需要监控其退出状态。

    另外,请注意,根据执行的操作(即命令差异),某些命令可能返回不同于零的退出状态

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-10
      • 2017-05-24
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 2011-11-01
      • 2018-05-13
      • 1970-01-01
      相关资源
      最近更新 更多