3

我有一个输出到 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前缀的二进制文件。这似乎会导致管道出现问题,这就是为什么我将命令包装在{…}所有输出进入管道中的原因。

4

3 回答 3

2

我没有可用的 zsh。

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

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

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

尝试

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

另外,你写

将 $cmd 的所有输出(形式 stderr 和 stdout)保存到文件 $logfile

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

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

我希望这有帮助。

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

于 2011-06-10T21:36:04.253 回答
1

不要在脚本中使用别名,使用函数(全局别名特别找麻烦)。并不是说您实际上需要这里的功能。你也不需要|| 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。

于 2011-06-10T23:16:45.477 回答
1

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

#!/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'(从下一个空行打印出错误 || 警告)打印出的内容比预期的要多得多,这使它看起来像命令没有工作。

于 2011-06-13T05:01:53.933 回答