【问题标题】:How to use stdout and stderr io-redirection to get sane error/warning messages output from a program?如何使用 stdout 和 stderr io-redirection 从程序中获取合理的错误/警告消息输出?
【发布时间】:2011-06-10 21:00:47
【问题描述】:

我有一个输出到 stdout 和 stderr 的程序,但没有以正确的方式使用它们。一些错误进入 stdout,一些进入 stderr,非错误内容进入 stderr,它会在 stdout 上打印很多信息。为了解决这个问题,我想做一个管道:

  1. 将$cmd 的所有输出(来自stderr 和stdout)保存到文件$logfile(不要将其打印到屏幕上)。
  2. 过滤掉 stderr 和 stdout 上的所有警告和错误消息(从警告|错误到空行)并仅对“错误”字词着色(将输出重定向到 stderr)。
  3. 将步骤 2 的输出保存到文件 $logfile:r.stderr。
  4. 使用命令中的正确退出代码退出。

到目前为止,我有这个:

$!/bin/zsh
# using zsh 4.2.0
setopt no_multios

# Don't error out if sed or grep don't find a match:
alias -g grep_err_warn="(sed -n '/error\|warning/I,/^$/p' || true)"
alias -g color_err="(grep --color -i -C 1000 error 1>&2 || true)"
alias -g filter='tee $logfile | grep_err_warn | tee $logfile:r.stderr | color_err'

# use {} around command to avoid possible race conditions:
{ eval $cmd } 2>&1 | filter
exit $pipestatus[1]

我尝试了很多东西,但无法让它发挥作用。我已经阅读了“从 Bash 到 Z Shell”,许多帖子等。我目前的问题是:

  1. 只有标准输入进入过滤器

注意:$cmd 是一个 shell 脚本,它调用带有 /usr/bin/time -p 前缀的二进制文件。这似乎会导致管道出现问题,这就是我将命令包装在 {…} 中的原因,所有输出都进入管道。

【问题讨论】:

    标签: bash zsh io-redirection


    【解决方案1】:

    我没有可用的 zsh。

    我确实注意到您的 {..}'d 声明不正确。

    在结束的 `}' 之前总是需要一个分号。

    当我在 bash 中添加它时,我可以满意地证明 stderr 被重定向到 stdout。

    试试

    { eval $cmd ; } 2>&1 | filter
    # ----------^
    

    你也写了

    保存 $cmd 的所有输出(从 stderr 和标准输出)到文件 $logfile

    我在您的代码中没有看到任何提及 $logfile 的内容。 您应该能够将所有输出放入日志文件(同时失去标准错误流的特殊性),使用

    yourCommand 2>&1 | tee ${logFile} | ....
    

    我希望这会有所帮助。

    附:由于您似乎是新用户,如果您得到对您有帮助的答案,请记住将其标记为已接受,和/或给它一个 +(或 -)作为有用的答案。

    【讨论】:

    • { eval $cmd } 在 zsh 下工作。 $logfile 出现在 filter 别名中。
    【解决方案2】:

    不要在脚本中使用别名,使用函数(全局别名特别找麻烦)。并不是说您实际上需要这里的功能。你也不需要|| true(除非你在set -e下运行,在这种情况下你应该在这里关闭它)。除此之外,您的脚本看起来还不错;什么东西呛到了?

    { eval $cmd } |
    tee $logfile |
    sed -n '/error\|warning/I,/^$/p' |
    tee $logfile:r.stderr |
    grep --color -i -C 1000 error 1>&2
    exit $pipestatus[1]
    

    我也不确定你所说的 sed 表达式是什么意思;我不太明白你的要求2。

    【讨论】:

    • 嗨 Gilles,sed 行打印出所有带有“错误”或“警告”的行,以及后面的所有行,直到空行。这是要求 2 的前半部分。另一半是 'grep --color ... 1>&2'
    • Gilles,感谢您提供有关 || true 的提示。我设置了setopt errexit(与set -e 相同)。
    【解决方案3】:

    原始帖子大部分是正确的,除了 Gilles 的优化(关闭 set -e,因此不需要 || true。

    #!/bin/zsh
    # using zsh 4.2.0
    setopt no_multios
    #setopt no_errexit # set -e # don't turn this on
    
    { eval $cmd } 2>&1 |
    tee $logfile |
    sed -n '/error\|warning/I,/^$/p' |
    tee $logfile:r.stderr |
    grep --color -i -C 1000 error 1>&2
    exit $pipestatus[1]
    

    让我感到困惑的部分是 stdout 和 stderr 的混合导致它们被交错,sed -n '/error\|warning/I,/^$/p'(从下一个空行打印出错误 || 警告)打印出的内容比预期的要多得多让它看起来好像命令不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      相关资源
      最近更新 更多