2011-06-10 55 views
3

我有一個程序輸出到stdout和stderr,但沒有以正確的方式使用它們。有些錯誤會導致stdout,有些會發生stderr,非錯誤的東西會轉到stderr,並且會在stdout上輸出很多信息。爲了解決這個問題我想使管道做:如何使用stdout和stderr io-redirection從程序中獲取理智的錯誤/警告消息輸出?

  1. 保存的$cmd到一個文件$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] 

我嘗試過很多事情,但不能讓它開始工作。我讀過「從擊到Z殼牌」,許多職位,等我的問題是目前:

  1. 只有標準輸入進入過濾器

注:$cmd是一個shell腳本調用前綴爲/usr/bin/time -p的二進制文件。這似乎會導致管道問題,並且爲什麼我將命令包裝在{…}中,所有輸出都進入管道。

回答

1

原來的職位主要是正確的,除了由吉爾優化(關閉所以|| true的不需要set -e

#!/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'(打印出來並且錯誤||警告到下一個空行)被打印出比期望的更多的東西,這使得它看起來像命令wasn 't working。

2

我沒有zsh可用。

我注意到您的{..}'聲明不正確。

在關閉`}'之前,您總是需要一個分號。

當我在bash中添加時,我可以證明我很滿意stderr被重定向到stdout。

嘗試

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

而且,你寫到

保存的CMD $(形式標準錯誤 和stdout)全部輸出到文件$日誌文件

我不在代碼中查看任何提及的$ logfile。 你應該能夠得到所有輸出到日誌文件(而失去標準錯誤流的specficity),與

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

我希望這有助於。

P.S.因爲你似乎是一個新用戶,如果你得到一個可以幫助你的答案,請記住將它標記爲已接受,並且/或者給它一個+(或 - )作爲有用的答案。

+0

'{eval $ cmd}'在zsh下工作,'$ logfile'出現在'filter '別名。 – Gilles 2011-06-10 23:20:50

+0

Doah,謝謝你指出。 – shellter 2011-06-11 01:27:29

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.

+0

嗨吉爾斯,sed行打印出所有行中有'錯誤'或'警告'的行和後面的所有行,直到一個空行。這是要求2的前半部分。另一半是'grep --color ... 1>&2' – dailyglen 2011-06-13 04:33:45

+0

Gilles,感謝關於「||」的提示。 TRUE'。我有'setopt errexit' set(與'set -e'相同)。 – dailyglen 2011-06-13 04:49:58

相關問題