Bash 如何使用stdout和stderr io重定向从程序中获取正常的错误/警告消息输出?
我有一个程序,输出到stdout和stderr,但没有以正确的方式使用它们。一些错误进入标准输出,一些进入标准输出,无错误的东西进入标准输出,它打印出标准输出的很多信息。要解决此问题,我想创建一个管道来执行以下操作:Bash 如何使用stdout和stderr io重定向从程序中获取正常的错误/警告消息输出?,bash,zsh,io-redirection,Bash,Zsh,Io Redirection,我有一个程序,输出到stdout和stderr,但没有以正确的方式使用它们。一些错误进入标准输出,一些进入标准输出,无错误的东西进入标准输出,它打印出标准输出的很多信息。要解决此问题,我想创建一个管道来执行以下操作: 将$cmd(从stderr和stdout)的所有输出保存到文件$logfile(不要将其打印到屏幕) 过滤掉stderr和stdout上的所有警告和错误消息(从警告|错误到空行),并只对“错误”字着色(将输出重定向到stderr) 将步骤2的输出保存到文件$logfile:r.st
$cmd
(从stderr和stdout)的所有输出保存到文件$logfile
(不要将其打印到屏幕)$logfile:r.stderr
$!/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到zshell”,很多帖子,等等。我目前的问题是:
注意:
$cmd
是一个shell脚本,它使用/usr/bin/time-p
前缀调用二进制文件。这似乎会导致管道出现问题,这就是为什么我要将命令包装在{…}
中,所有输出都进入管道。我没有可用的zsh
我确实注意到您的{..}
'd语句不正确
在结束“}”之前总是需要分号
当我在bash中添加这一点时,我可以满意地证明stderr被重定向到stdout
试一试
还有,你写了
保存$cmd的所有输出(表单stderr)
和stdout)转换为文件$logfile
我没有看到你的代码中提到$logfile。
您应该能够使用
我希望这有帮助
另外,当您看起来是新用户时,如果您得到一个有助于您的答案,请记住将其标记为已接受,并/或给它一个+(或-)作为有用的答案。不要在脚本中使用别名,请使用函数(全局别名特别麻烦)。并不是说你真的需要函数。您也不需要
|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的优化(关闭
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'
(从打印出来,错误| |警告到下一个空行)打印出来的内容比预期的要多得多,这使得命令似乎不起作用。{eval$cmd
在zsh下工作。$logfile
出现在过滤器
别名中。嗨,Gilles,sed行打印出所有包含“error”或“warning”的行以及后面的所有行,直到出现一个空行。这完成了需求2的前半部分。另一半带有“grep--color…1>&2”Gilles,感谢关于|t的提示rue
。我有setopt errexit
set(与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]
#!/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]