[轉載請註明出處] http://kezeodsnx.pixnet.net/blog

作者: kezeodsnx

每個cmd都需要stdin, stdout, stderr,正常情況下,cmd從stdin (keyboard)讀資料,輸入結果到stdout (monitor),輸出錯誤到stderr (monitor)。如果這3個file descriptor有問題,就會出現以下情形: 先把stdout 關掉,再下ls:

user@user-ubuntu:~$ exec >&-
user@user-ubuntu:~$ ls
ls: write error: Bad file descriptor

xterm 也在initialize時,開啟了3個terminal device(/dev/pts/n),之後的bash均繼承xterm的file descriptor。

Shell 有10個file descriptor,即0~9。其中0, 1, 2就是大家都知道的stdin, stdout, stderr。剩下的比較少看到有人用,我自己是沒用過。通常把0, 1, 2導來導去就很複雜了。3~9通常是給opening file使用,一種用法為在一連串的I/O redirect後,為了復原,可在redirect之前先複製到3~9其中一個,將來再複製回來。

與I/O redirect相關的cmd有pipe (|), tee, exec。

pipe蠻常用,是把目前的stdin 導到下一個cmd的stdin,例如ps aux |grep init,將ps的結果(stdout)當成grep的stdin。

tee是將stdout複製(到檔案),通常我的用法是make | tee /home/user/build.log。

exec蠻特別,通常的理解是取代,但當其操作的對像是file descriptor時,不會有取代發生。

2個rule:

1. < 是input,> 是output

2.<預設值是0,>預設值是1。即<與0<同,>與 1>同。下面的例子若有疑問,可試著代入展開。

熱身:

>&n: 即1>&n,也就是將stdout複制給 file descriptor n (使用dup(2))

<&n: 即0<&n,將file descriptor n 複製到stdin

<&-: 即0<&-,關閉stdin

>&-: 即1>&-,關閉stdout

了解之後,可看實例。如果你是使用ubuntu,請看/etc/rc6.d/S40umountfs,其中有段如下

do_stop () {
        exec 9<&0 </proc/mounts

                       :

         exec 0<&9 9<&-

第一行就是stdin複製到file desciptor到9 (因為馬上要redirect stdin了,先備份起來,以便之後將stdin restore),然後再把/proc/mount當成stdin。之後進行一連串的umount後,再把file descriptor 9 restore 到stdin,最後把file descriptor關閉。

幾個example:

2>&1: 把stderr複制到stdout。乍看之下,好像沒什麼特別的,因為stderr和stdout都是monitor。但當stdout是其他file 或file descriptor時,效果就不同了

例如:

#stdout無輸出,因此1>log後,log為市。stderr還是由monitor輸出err
user@user-ubuntu:~$ bad_cmd > log
bash: bad_cmd: command not found
user@user-ubuntu:~$ cat log

#將stdout 導到log, 再將stderr複製到stdout,因此err都導到log裡
user@user-ubuntu:~$ bad_cmd > log 2>&1
user@user-ubuntu:~$ cat log
bash: bad_cmd: command not found

 

kezeodsnx 發表在 痞客邦 PIXNET 留言(0) 人氣()