[問題] script如何導出stderr

看板Linux作者 (nahgnimiast)時間14年前 (2011/10/28 04:04), 編輯推噓2(2093)
留言95則, 4人參與, 最新討論串1/1
我想將stderr的訊息額外導到檔案, 也就是說error訊息除了輸出到螢幕之外 ,還要輸出到檔案。 如果是stdout的話,可以使用tee來達成, 但stderr要怎麼做呢? -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.121.236.62

10/28 07:23, , 1F
2>tee
10/28 07:23, 1F

10/28 07:23, , 2F
啊, 好像不太對 ...
10/28 07:23, 2F

10/28 07:41, , 3F
如果可以接受stderr和stdout同一檔案,那就是 2>&1 再 |
10/28 07:41, 3F

10/28 07:42, , 4F
myprogram 2>&1 | tee output-file
10/28 07:42, 4F

10/28 07:42, , 5F
如果不行,那就要效法上次網友貼的 gdb 大法
10/28 07:42, 5F

10/28 07:43, , 6F
上一行的不行,是指不能接受 out err 同一檔案
10/28 07:43, 6F

10/28 07:47, , 7F
剛才想到,不用 gdb 也可以做
10/28 07:47, 7F

10/28 07:48, , 8F
myprogram 2>output-file ; tail -f output-file
10/28 07:48, 8F

10/28 09:25, , 9F
f(){ echo 1>&3; ls abc 2>&1; }; f 3>&2 把stdin/err對調
10/28 09:25, 9F

10/28 09:46, , 10F
ls exist nonexist 3>&1 1>&2 2>&3 同上,接下來可用tee
10/28 09:46, 10F

10/28 23:47, , 11F
b大的方法不合我用,順序應該會不對
10/28 23:47, 11F

10/28 23:47, , 12F
k大的方法,我要試試能不能用
10/28 23:47, 12F

10/29 00:03, , 13F
所謂順序不對是什麼意思?
10/29 00:03, 13F

10/29 00:04, , 14F
我猜是tail會漏掉一些快速印出的較早內容.那就改一下
10/29 00:04, 14F

10/29 00:06, , 15F
last的參數,讓它能印出所有一開始內容就好
10/29 00:06, 15F

10/29 00:09, , 16F
打錯, 是 tail 的參數
10/29 00:09, 16F
myprogram 2>output-file ; tail -f output-file 因為我要導出make的stderr訊息 但是除了錯誤訊息會到stderr,警告訊息也會, 且只有error時,才會停止,警告不會。 所以上面的方法不能用。 ※ 編輯: tsaiminghan 來自: 59.121.233.249 (10/29 02:21)

10/29 08:31, , 17F
你的意思是如果只有警告,tail 不會結束,而你希望make完都
10/29 08:31, 17F

10/29 08:31, , 18F
一律停止?
10/29 08:31, 18F
不是。因為編譯android時,一定會產生警告 我目的如下 我寫了一個編譯android的script 在make時,如果發生error,我會將error訊息存入 檔案,然後寄出來,但是目前發現光只有error很難 debug, 所以想除了stderr之後,也存一份完整的log (包括stdout , stderr),目前就是卡在這裡。 因為編譯android時,會有很多warning訊息,所以 stderr的輸出內容有兩種訊息,照上面的作法是將 stderr的訊息最後接在完整log的後面,這樣log的 順序應該會不正確,因為warning的訊息可能是很早 就產出的。 <=說明不是很詳細,如果看不懂的話,我在寫更詳細。

10/29 13:59, , 19F
警告是從stdout出來還是stderr? 如果是前者那簡單,如果是
10/29 13:59, 19F

10/29 14:00, , 20F
從stderr(跟error訊息一起)出來,那就變成需要一個軟體
10/29 14:00, 20F

10/29 14:00, , 21F
filter. 把 error 分離出來.
10/29 14:00, 21F

10/29 14:01, , 22F
我懂了,看到你第一次編輯回言,警告也是從stderr出來.
10/29 14:01, 22F

10/29 14:01, , 23F
那只有寫個軟體filter了.
10/29 14:01, 23F

10/29 14:55, , 24F
沒寫過filter,暫時不打算這麼做,先看看k大的方法行
10/29 14:55, 24F

10/29 14:55, , 25F
不行
10/29 14:55, 25F

10/29 16:07, , 26F
k大的方法一樣是在OS層面處理,你的問題是Ap應用層面(把
10/29 16:07, 26F

10/29 16:07, , 27F
所需的error訊息特別過濾出來),應該是一樣不行.
10/29 16:07, 27F

10/29 16:08, , 28F
filter也沒什麼特別, a | b | c 的 b 就叫 filter
10/29 16:08, 28F

10/29 16:08, , 29F
你把error/warning的文字範例提供一下,說不定馬上有人可以
10/29 16:08, 29F

10/29 16:09, , 30F
用 grep/sed/awk 等工具立刻組一個給你
10/29 16:09, 30F
原來filter是這個意思。 另外make執行時,發生的錯誤訊息應該不是很固定吧? 所以filter應該不好寫。 且本來stderr和stdout輸出就是分開的,現在把它合起來,然後另外寫個 filter來把特定字串找出來,我覺得真是作白工XD k大的方法說可以把stdout/err對調,如果真的可以的話,配合tee,應該可以 達成我的需求。 ※ 編輯: tsaiminghan 來自: 59.121.130.222 (10/29 16:52)

10/29 16:55, , 31F
可是你前面不是說警告也走 stderr 出來?還是我誤解了?
10/29 16:55, 31F
是啊, 警告也是從stderr出來,但是因為發生error時,error訊息會在stderr最後面, 所以輸出的檔案我只要看最後面就可以抓到錯誤訊息。 但是因為光錯誤訊息,沒有stdout輸出,不容易知道發生什麼事,所以才希望有完整 的log,然後由error訊息去完整log中找到發生問題的點,看發生什麼事。 ※ 編輯: tsaiminghan 來自: 59.121.130.222 (10/29 17:02)

10/29 16:58, , 32F
還是搞了半天,你只想把stdout, stderr 的內容照時間順序合
10/29 16:58, 32F

10/29 16:59, , 33F
併顯示並且log? 如果真的是這樣,那解法不用這麼複雜.
10/29 16:59, 33F

10/29 17:00, , 34F
就用傳統的 2>&1 把 stdout dup 給 stderr 就好.
10/29 17:00, 34F

10/29 17:01, , 35F
myprogram 2>&1 | tee output-file
10/29 17:01, 35F
還有 22 則推文
10/29 17:18, , 58F
我要編譯的是android....編一次大約要50分鐘XD
10/29 17:18, 58F

10/29 17:18, , 59F
不客氣,希望有用就好.
10/29 17:18, 59F

10/29 17:19, , 60F
所以K大的方法,如果真的可以把stdout和err調換
10/29 17:19, 60F

10/29 17:19, , 61F
看來用程式把 error 以 pattern 來 grep/sed/awk 抓出來
10/29 17:19, 61F

10/29 17:19, , 62F
比較有希望.
10/29 17:19, 62F

10/29 17:19, , 63F
配合tee應該可以做到
10/29 17:19, 63F

10/29 17:20, , 64F
把stdout,stderr 的descriptor互換,沒有改變什麼啊?
10/29 17:20, 64F

10/29 17:21, , 65F
現在的問題是只一次 make,你要一次產生單一時序輸出檔,又
10/29 17:21, 65F

10/29 17:21, , 66F
有一個單純只有 stderr 的檔,那是基本上相斥的事.
10/29 17:21, 66F

10/29 17:22, , 67F
tee可以把stdout的資料分流到stdou和檔案
10/29 17:22, 67F
我不確定行不行但是 想法如下 如果stdout和stderr換過來 ====script A.sh====== make | tee err.log ================== ====script B.sh==== a.sh &> all.log ※ 編輯: tsaiminghan 來自: 59.121.131.72 (10/29 17:24)

10/29 17:23, , 68F
事實上,我剛熊熊才想到 17:01 那行根本是脫褲子放X. XD
10/29 17:23, 68F

10/29 17:24, , 69F
一般程式一開始 stdout 和 stderr 都只向終端機.
10/29 17:24, 69F

10/29 17:24, , 70F
tee 只是讓你看畫面兼log至檔案.現在問題是stdout和stderr
10/29 17:24, 70F

10/29 17:25, , 71F
一開始是一體的. 你要分開它們,就不能一起tee
10/29 17:25, 71F

10/29 17:26, , 72F
因為stdout和stderr一開始是都指向tty/pty,所以你掉換還是
10/29 17:26, 72F

10/29 17:26, , 73F
同一個東西,會tee到的內容還是一樣. XD
10/29 17:26, 73F

10/29 17:28, , 74F
了解...那你的意思是tee是抓不到stderr的資訊
10/29 17:28, 74F

10/29 17:28, , 75F
我想了一下. 是有可能... 因為 pipe 只針對 stdin/stdout
10/29 17:28, 75F

10/29 17:28, , 76F
即使我把fd的輸出換過來?
10/29 17:28, 76F

10/29 17:30, , 77F
不過,再想一下,還是怪怪的. 只能等你試看看了.
10/29 17:30, 77F

10/29 17:30, , 78F
整個麻煩就在於你同時需要合流和分流. 調換stdout/stderr
10/29 17:30, 78F

10/29 17:31, , 79F
是會讓 tee 能從它自己的 stdin 取得 make 的 stdout (包
10/29 17:31, 79F

10/29 17:31, , 80F
含error/warning,因為out/err有swap過)
10/29 17:31, 80F

10/29 17:31, , 81F
好啊,星期一時再試試看
10/29 17:31, 81F

10/29 17:32, , 82F
但是因為經過pipe,就分流了,所以我懷疑b.sh就算抓到全部內
10/29 17:32, 82F

10/29 17:32, , 83F
容,時序也會亂掉.更何況我不確定b.sh是否能抓到全部的log
10/29 17:32, 83F

10/29 17:33, , 84F
簡單講,只有(out,err)合流,才會保證有正確的時序
10/29 17:33, 84F

10/29 17:33, , 85F
似乎很難一次做兩個相反目的的工作.
10/29 17:33, 85F

10/29 17:34, , 86F
你要不要貼一下wanring/error範例,用filter搞不好還容易些
10/29 17:34, 86F

10/29 17:34, , 87F
這倒是個問題,就算順序亂掉了,我也不一定能發現
10/29 17:34, 87F

10/29 17:35, , 88F
我17:01的那一行,在(out,err)合流的前提下,又不是脫X放X了
10/29 17:35, 88F

10/29 17:36, , 89F
真弄不出來的話,也只是照現在的清況繼續用而已
10/29 17:36, 89F

10/29 17:36, , 90F
那行確保out,err即使app的fd不同,但用同一個OS的內部fd
10/29 17:36, 90F

10/29 17:37, , 91F
filter就再看看吧,老實說發生error的訊息會長什麼樣
10/29 17:37, 91F

10/29 17:37, , 92F
那麼我建議你用 17:01 那行,確保時序一定正確.
10/29 17:37, 92F

10/29 17:37, , 93F
我現在也不是很確定
10/29 17:37, 93F

10/29 17:40, , 94F
等你測試好了,再回篇新的(舊的這篇可能洗出畫面了),我也有
10/29 17:40, 94F

10/29 17:40, , 95F
興趣知道結果.
10/29 17:40, 95F
測試結果不行 輸出互換ok,導出也ok,但 tee的使用跟我想像中不太一樣 以下執行時 xxx | tee zzz.log 會先把stderr印出,然後再印出stdout,因此順序會不對。 所以如果要順序正確,一定要把stdout和stderr導 到同一輸出才行,但導到同一輸出,就做不到分流的目的 ※ 編輯: tsaiminghan 來自: 59.121.128.220 (10/31 23:39)
文章代碼(AID): #1EgRbBd8 (Linux)