網頁標題: [C語言] 請問怎麼攔截pipe前一個程式的stderr?
 



知識問題 | 
[C語言] 請問怎麼攔截pipe前一個程式的stderr? 發問者: (︶︿︶ )_╭∩╮ ( 初學者 5 級) 
發問時間: 2009-05-23 18:34:32 
解決時間: 2009-06-06 18:49:08
解答贈點: 15 ( 共有 0 人贊助 )
回答: 2 評論: 0 意見: 20

網友正面評價

100%
( 共有 4 人評價 )
[ 檢舉 ]
[C語言] 請問怎麼攔截pipe前一個程式的stderr?


例如 Windows 命令列下,

A.exe | B.exe

B.exe 要怎麼攔截 A.exe的 STD ERR(標準錯誤輸出) ?
2009-05-23 18:35:14 補充

我用 C scanf 都只能讀到前一個程式的STDOUT.

2009-05-24 23:01:07 補充

回答跟意見都很精采,
我是在make file裡面用的,
最主要是因為 原本make file 內寫

A.exe 2> stderr.log

我想寫成 A.exe | B.exe
然後 B.exe 可以獲得 A.exe的 STDOUT 跟 STDERR
但是實際上只能抓到STDOUT

2009-05-24 23:14:10 補充

Jacob,

感謝您的回答,

這個A | B 2>&1 我自己也試過
這樣 STDERR 會寫到 B.exe檔案上, 破壞了 B.exe檔案內容.

2009-05-24 23:15:24 補充

有空的話請幫忙回答這個問題:

一樣是在make file 內的問題:
http://tw.knowledge.yahoo.com/question/question?qid=1509052411383

2009-05-26 00:28:32 補充

Jacob 你的解法可能是對的,
但是我是在make file 內寫的,
還用dos 的 IF 包起來:
例如

(IF .... & \
(X.exe ....) & \
(A.exe .... ) & \
(if ERRORLEVEL 1 .... ) & \


很奇怪, 這個ERRORLEVEL
若在 (A.exe & echo %ERRORLEVLE% .. )求值 就是0
若是放在 下一列的 (if ERRORLEVEL ...) 求值就是1

2009-05-28 16:17:50 補充

更正拼字: A.exe & echo %ERRORLEVEL% .. )

2009-06-01 14:54:37 補充

我是把 Windows Command Prompt 語法 寫在 makefile 上,

例如:


@if /I "$(AA)" EQU "TRUE" \

2009-06-01 14:55:33 補充

我知道ERRORLEVEL不是環境變數,
而是上一個程式結束的傳回值.

最佳解答發問者自選 回答者: Jacob Lee ( 大師 4 級 ) 
代表知識團: C/C++程式語言討論研究
擅長領域: C&C++ | 作業系統 
回答時間: 2009-05-23 21:33:41
[ 檢舉 ]

此題無解!
除非遇到專研 Windows OS-Coding 超超超極秘技的人!



StdiErr 通常是定給 螢幕。
而 pipe 只傳 StdOut 給後者的 StdIn
這些動作都是由 OS 執行時設定的。
既然 OS 沒有傳 A 的○○給 B,B 要去撈 OS 裡的東西,包括:
1. 我是被哪東東 pipe 過來的(這東東確定有得撈!但絕對是 OS dependent!)
2. 那東東的 StdErr 在哪?
3. 怎麼改 StdErr(問題是:改了不一定有效!)



而,另一個根本性的問題是:
Pipe 的定義是平行執行!
MS-DOS 到 6.22 以前,都是假平行;
但,事隔一萬年了,現在的 Windows 應該已經是真平行了!



無論真假,B 不一定能在 A 有 StdErr 前,就改掉 A 的 StdErr 的設定!
尤其是在假平行下,那是絕對無解!
若是真平行,也不能保證!



所以,確定此題無解!



= = = =



在程式設計的領域無解,不代表在電腦的領域無解!



你要找的是 OS Command Shell!
有的 Shell 有支援!
不同的 Shell 使用的方法不同,如: 2| 或 &|
不過,這兩招在 XP 的 Shell 確定不能用!



= = = =



所以,你不用再到 C 的程式領域找!
找到了你可能也看不懂!
看懂了也不穩定,也有嚴重的 可攜性 的問題!



找 Shell 的玩家比較快!


2009-05-23 21:42:41 補充

若你沒要同時執行的效果,XP 倒是可以作弊!

我弄一下,再補給你。

2009-05-23 22:02:43 補充

A > t.txt 2>&1
B < t.txt
del t.txt

這樣就可以了

2009-05-23 22:08:53 補充

剛發現一個神奇的用法,你試試看!
如果合用,應該比上述法更好

A | B 2>&1

2009-05-24 07:45:25 補充

可以請 DeeR
 詳看題目
及
 所引用的那篇

再武斷地說:
 〝絕對〞有解
嗎?


兩年前?五年前我就在做平行運算了,會不知道 sryang 說的那個方法?
(當然,它們只是相關:
  平行運算不限用在那方法;
  那方法不限用在平行運算。
)

2009-05-25 06:31:54 補充

= = = =

不好意思,是我的錯! 我打錯東西!

不過,我根據我打錯的,
 沒把 B 給毀了耶!
 只是沒達到效果!
希望沒造成你的災難!

你是不是打成了
 A.exe > B.exe 2>&1
我說錯的是
 A.exe | B.exe 2>&1
或
 A | B 2>&1
= = = =

正確的應該是:

A 2>&1 | B

你試試看,應該
 不會把 B 給毀了
 能正確地把 A 的 StdOut 及 StdErr 都傳給 B 的 Stdin

2009-05-26 12:58:17 補充

ErrorLevel 不是環境變數!

版大的
(A.exe & echo %ERRORLEVLE% .. )
會是 0 的原因,就是因為 沒有這變數,把它當變數印,當然是 0

而放在 下一列的 (if ERRORLEVEL ...) 求值就是1
因為 意見 017 說的那些東西,
 其中有人 的 return code (main function 的 return 值) 是 1

2009-05-26 16:57:59 補充

Makefile 我也玩過好幾年,它的確和 bat 有很大的不同。

至於版大為何會在 makefile 裡用了 pipe 和 & 等,就要問他了。
或許版大是以 bat 的方式,操作類似 makefile 的效果。

把 ErrorLevel 變環境變數的做法,我也寫過數次;
還做過更複雜變化,如:亂數、變成 Menu、用↑↓←→移動光棒等。

= = = =

版大,若你要把ErrorLevel 變成環境變數,要注意你的拼字!
你目前放上來的,字有拼錯。
但,M$ 的 OS 裡,環境變數是沒有 ErrorLevel 的。
(除非最近它又新延伸了。至少,Vesta還沒有)

2009-06-01 15:47:56 補充

大部份的 makefile 有它自己的語法,不是單單吃 OS 的 command shell 的東西。

如果是吃 OS 的 command shell的語法,它會變成 OS dependent 的東西,不太好用!

2009-06-02 11:24:12 補充

鍋子放到瓦斯爐上,能不能拿來烤東西? 可以!
好用嗎? 當然不!
能用嗎? 當然可!

你若有烤箱,為何要用鍋子?


寫程式/操作電腦,也是一樣!
你要好寫介面,有/會 VB, Java,為何要用 C?
C 的專長,就不是在做介面!

makefile 也一樣!
就算你今天玩出來,
 1. 換用下一版的 make、
 2. 拿去另一種的 make、
 3. 兩年後用同一種同一版的 make
都不一定會成功!( 3. 如樓下講的:你忘了!)


還是不要做這樣的事吧!
把時間花在較普遍、長久、有用的事上。
(請想想,為何一堆東西在講 可攜性/相容性?)

發問者評價:
感謝您的熱心回答,
受益無窮
其他回答(1) 意見(20)
001
回答者: DeeR ( 初學者 3 級 ) 
回答時間: 2009-05-24 00:06:22
[ 檢舉 ] 兩年前 就有人問過這類的問題了.

http://delphi.ktop.com.tw/board.php?cid=30&fid=69&tid=90571

你可以去看看.
sryang 有提供詳細的說明.

windows XP 用的.
絕對有解. 2009-05-26 07:56:35 補充

ERRORLEVEL 這個東西, 應該是一個"環境變數", 你用環境變數的方法去試看看吧.

2009-05-26 14:00:00 補充

不是環境變數,就把它變成環境變數囉。
http://www.robvanderwoude.com/errorlevel.php
這邊有教怎麼變。

至於。發問者說要放在 Makefile �堙C確實。它的寫法會跟你用 bat 法不一樣。
make 是否可以像 bat 那樣操作 errorlevel 得要測試看看才知道。
而且。我玩過的3-4種 make 所用的語法, 還是有點差異的。

2009-06-01 19:44:59 補充

問題是......當你的 make 出現 error 時.理當要停下來了呀.
要是再 make 下去.已經是無意義的事了.

如果你是要利用 make 來做 if case..... 的事情.
那是不是應該要變成要分開寫成不同的 target?

make 有 make 的目的.它是要讓你做專案管理好管.

bat(shell) 有 bat(shell) 的目的. 它們是讓你省掉重覆的動作的.

花太多時間在做這種"超人"的動作. 只是顯得你"好利害"(是不是真利害不知道.)
但是.隔一段時間後.你又忘了當時的寫法, 維護上就會出問題了.

還是用標準動作就好吧.

1

001
意見者: novus ( 專家 5 級 ) 
擅長領域: C&C++ | 物理 
發表時間: 2009-05-23 23:37:50
[ 檢舉 ] 有相當程度需要靠 case by case

之前有寫過一個可以和gdb互動的

原c++ class在此
http://www.phpbbserver.com/graphicsparalle/viewtopic.php?p=636&mforum=graphicsparalle#636
我的做法是利用windows api
在啟動目的process的時候順便把stdout和stderr綁在一起 
002
意見者: novus ( 專家 5 級 ) 
擅長領域: C&C++ | 物理 
發表時間: 2009-05-23 23:43:15
[ 檢舉 ] 這是需要比較大的互動功能,或是對child process有比較大控制權的時候才需要這麼麻煩

否則應該盡量使用dos本身的pipe重導 
003
意見者: Jacob Lee ( 大師 4 級 ) 
擅長領域: C&C++ | 作業系統 
發表時間: 2009-05-24 07:40:54
[ 檢舉 ] 我認為 回答者 002 DeeR http://tw.knowledge.yahoo.com/my/my?show=AE03201838 誤解了版大的題意。

〝攔截〞 pipe前一個程式的 stderr
也就是說:不是由 A 產生 pipe 給 B

他所引的那篇,用的也是 shell 重新轉向,還比我寫的方法少!
而其中與程式有關的,寫的是『由 A 產生 pipe 給 B』

所以,他說的〝windows XP 用的. 絕對有解.〞,
在版大的文意上,是絕對不錯誤的!

= = = = 
004
意見者: Jacob Lee ( 大師 4 級 ) 
擅長領域: C&C++ | 作業系統 
發表時間: 2009-05-24 07:41:24
[ 檢舉 ] (1) 而 Novus 寫的也是『由 A 產生 pipe 給 B』。
(2) 但,他明說:〝否則應該盡量使用dos本身的pipe重導〞

根據 (1),我寫的〝程式領域無解〞仍是正確的!
根據 (2),和我回答的後半:建議版大用 shell 是一致的

另外,shell 既然有提供,何必另尋它法?

再來,要是 無法取得 A 的 source coe,
『由 A 產生 pipe 給 B』就完全行不通!

或是,A已寫得很...,要改由 A 建 Pipe ...會產生一堆 Bug!
所以,仍強烈建議:使用我寫的方法去重導!
不要用『由 A 產生 pipe 給 B』! 
005
意見者: Jacob Lee ( 大師 4 級 ) 
擅長領域: C&C++ | 作業系統 
發表時間: 2009-05-24 07:41:50
[ 檢舉 ] 除非,你要研究的,是 由程式建 pipe (的平行法)。
不然,如 Novus 所言:不建議自己寫 pipe!

也就是說:要不要版大題目寫錯,
 『由 A 產生 pipe 給 B』
是完全錯誤的方法:
 1. 不合題意
 2. 不能解決拿不到 A 的 source 的狀況
 3. 要花一些工作時間寫成
 4. 方法複雜,但程式改變反而較性少
 5. 發展過程會產生一堆 bug!


參考資料:五年以上平行運算研究 
007
意見者: Jacob Lee ( 大師 4 級 ) 
擅長領域: C&C++ | 作業系統 
發表時間: 2009-05-24 08:19:01
[ 檢舉 ] 竟然有重大錯字!

意見 003 最後一句
 在版大的文意上,是絕對〝不〞錯誤的!
應該是
 在版大的文意上,是絕對〝 〞錯誤的!

意見 005 中間
 也就是說:要不〝要〞版大題目寫錯,
應該是
 也就是說:要不〝是〞版大題目寫錯

= = = =

根據版大的題意:『B 攔截 A』,不是
 A 產生給 B
 有什方法可以讓 B 知道 A 的
攔截,本身代表的就是不是〝極〞中規中矩的方法!
也就是說:A 產生 pipe 給 B,就根本不是〝B〞〝攔截〞A

而,A 產生給 B,若能取得 A 的 code,只要把 stderr 換成 stdout 就好了
所以,很明顯:版大問的,不是 由 A 產生 pipe 給 B 
008
意見者: Jacob Lee ( 大師 4 級 ) 
擅長領域: C&C++ | 作業系統 
發表時間: 2009-05-24 08:20:55
[ 檢舉 ] 寫意見 003 ~ 005 時漏引:Novus 也認為:由 A 產生 pipe 給 B 是 case by case 的作法。

而題目:〝攔截pipe前一個程式的stderr〞
及內文:〝B.exe 要怎麼攔截 A.exe的 STD ERR〞
二度表明:不是 A 產生給 B


所以,回答者 002 強週〝絕對〞有解,似乎是對
 題目
 我的回答
 sryang 的作法
 OS 運作
不太了解 
009
意見者: novus ( 專家 5 級 ) 
擅長領域: C&C++ | 物理 
發表時間: 2009-05-24 09:30:59
[ 檢舉 ] 補充一下

我的程式示範的就是用 B 攔截 A 的 pipe,完全不需侵入式的做法,也就是說不必動到 A 的 source code。

基本上這和 Windows下的重導完全相同,只是從比較底層的地方著手,因此可以做到比較細微的控制。 
010
意見者: novus ( 專家 5 級 ) 
擅長領域: C&C++ | 物理 
發表時間: 2009-05-24 09:37:59
[ 檢舉 ] 為什麼說有某種程度上需要case by case?

因為並不是所有用console的程式都使用標準的pipe,像我上面的程式要抓 cmd、ping、gcc、gdb 的輸出都沒問題,但是像 telnet 就沒辦法啦。

因為telnet要畫彩色文字,就不是用標準的pipe 
011
意見者: DeeR ( 初學者 3 級 ) 
發表時間: 2009-05-24 09:59:59
[ 檢舉 ] J 大. 也許您五年前才在玩平行. 小弟也知道, 您的功力不錯.
不過. 有時候. 您也要體會一下, 下頭的這些平民百姓的苦呀.
他們是有問題不會問. 不會用"正規"的表達方式來表達問題.
所以, 不要把一個簡單的問題, 想那麼複雜.
這就像二十幾個博士, 去考初等考, 沒半個考上一樣. 其實, 那些博士真的不懂嗎?
也許, 在某些方面. 懂得比出題的多. 還知道題目封鎖不完全,
會有此題無解或是些題多解出現在單選.
那當然考不上囉.

找知識  搜尋全部 搜尋煩惱 進階搜尋 雅虎資訊 版權所有 (c) 2011 Yahoo! Taiwan. All Rights Reserved. 「本服務設有管理員」 服務條款 隱私權政策
知識+ 之問答內容是由參與Yahoo!奇摩知識+ 之網友提供,僅供參考,Yahoo!奇摩不保證其正確性。




回 · 搞怪電腦基本常識 這一篇文章封面


本文張貼者:校校鴿〔張貼時間:民國100年2月21日(星期一)8點56分〕 | 寫信給校校鴿

部落格首頁


學習的故鄉首頁
本站公告:〔您越需要我們,我們就越有創意〕 本站說明書:〔發現故鄉還有改進的地方,請來信告訴原丁們〕
觀察應用學習點數 :〔咱的故鄉有您的參與,會使我們有更大的發揮空間,展現更豐富精彩的學習畫面〕 〔期待藉由無障礙網頁設計,能讓視障小朋友更愛看書、更愛寫作且更愛學習〕:盲用電腦「心得分享」
〔為了讓我們有乾淨的學習環境,請勿任意在本站散播商業廣告與不合法文件或聯結〕:本站宣示