[轉載請註明出處] 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
留言列表