10.17.2015

Linux I/O Redirection and File Description overview

最近在Study這一本書:Linux 程式設計教學手冊,我買的時候比較早,是3rd Edition,但早在2008年時就已經推出4th Edition了!! 不過這不是重點。這一本書寫的不錯,主要都是在介紹Linux User Space API Programming,而且又不需要太艱澀的OS知識。還有另外一本,我也是買了好幾年了,「一直都沒有翻閱」:Advanced Programming in the Unix Environment 國際中文版,這一本寫的就比較進階一些....因為這一本書當時是和另外一本同時推出的:TCP/IP Illustrated. Vol.1 (國際中文版) (所以我兩本都買了)。

裡面的第13章─處理程序間的通訊:管線 (pipe),自己只看得懂前面一半,後面那一半就不太清楚再寫些甚麼,一方面也是因為目前為止在工作上也沒有管線的實務經驗。

裡面的I/O重新導向 (I/O Redirection)檔案描述子 (File Description),自己並沒有搞得很清楚,只能先把一些懂的部分記下來....

Linux的世界裡,每一個行程 (Process,進程)都是透過File Description (檔案描述子, FD)來處理資料。

而每一個行程有256個FD。

前3個FD是屬於標準I/O的部分,FD0: STDIN (標準輸入), FD1, STDOUT (標準輸出), FD2: STDERR (標準錯誤輸出)

我們可以透過Shell Script指令來修改標準I/O。例如:

[root@localhost]# cat -n /etc/resolv.conf

也可以寫成:

[root@localhost]# cat -n 0< /etc/resolv.conf

cat這一支程序,要從/etc/resolv.conf做標準輸入 (FD0);所以也可以把0給省略:

[root@localhost]# cat -n < /etc/resolv.conf

因'<'的FD預設值就是0,所以0才可以省略;同理:

[root@localhost]# echo "01234" 1> /root/TEST.TXT

用echo這一支程序,把字串"01234"做標準輸出到/root/TEST.TXT這一個檔案。'>'的FD預設值是1,所以1也可以省略,等價於:

[root@localhost]# echo "01234" > /root/TEST.TXT

問題來了:

[root@localhost]# echo "01234" 2> /root/error.log

這一行指令是甚麼意思?? 應解讀為:當執行echo "01234"指令時,若有什麼錯誤訊息,就把它導入到/root/error.log這一個檔案。

因'>'的FD預設值是1,所以2就不能省略,因為一省略就變成標準輸出 (stdout),而不是標準錯誤輸出 (stderr)。

再看一個更進階一點的:

[root@localhost]# rm -vf /root/TEXT.INI > /dev/null 2>&1

這一行指令該如何解讀?? 「移除/root/TEXT.INI這一個檔案,移除檔案的過程中,有任何的『標準輸出』訊息,就把它導入到/dev/null;若有任何的『標準錯誤』訊息,也同時導入到/dev/null。」等同於:

[root@localhost]# rm -vf /root/TEXT.INI 1> /dev/null 2>&1

'&'符號就跟大部份的程式語言一樣,代表「並、且、和、同時」的意思,所以也同時等價於這2行指令:

[root@localhost]# rm -vf /root/TEXT.INI 1> /dev/null
[root@localhost]# rm -vf /root/TEXT.INI 2> /dev/null

所以,還可以寫成:

[root@localhost]# rm -vf /root/TEXT.INI 2> /dev/null 1>&2

「移除/root/TEXT.INI這一個檔案,移除檔案的過程中,有任何的『標準錯誤』訊息,就把它導入到/dev/null;若有任何的『標準輸出』訊息,也同時導入到/dev/null。」

問題又來了,那....什麼是「標準輸出訊息」和「標準錯誤訊息」??

倘若/root/TEXT.INI這個檔案存在,我們執行時的狀況應該是這個樣子:

[root@localhost]# rm -vf /root/TEXT.INI
已移除 '/root/TEXT.INI'

當我們執行rm這一支程序時,因為執行成功,所以程序回報給我們「已移除 '/root/TEXT.INI'」,這就是「標準輸出訊息」。

[root@localhost]# kill -s SIGKILL 2192
bash: kill: (2192) - 沒有此一程序

「bash: kill: (2192) - 沒有此一程序」,這就是「標準錯誤訊息」,因為根本就沒有這個PID。

所以,當我們執行「rm -vf /root/TEXT.INI 2> /dev/null 1>&2」指令時,「不管有甚麼訊息,我們通通都把它導入到/dev/null」。

沒有留言:

張貼留言