在shell使用的I/O重導,其行為其實還有很多有趣的部分。一般常使用的就是<和>,但是它們其實不只能重導stdin和stdout,重導的方向也不只有檔案或裝置而已。
<和>其實前方可以加數字,就是file descripter,若不特別指明,那麼<預設會是0<,>預設是1>,其中0即為stdin的file descripter,1為stdout的file descripter[?],而2就是stderr了。[?]
<和>其實前方可以加數字,就是file descripter,若不特別指明,那麼<預設會是0<,>預設是1>,其中0即為stdin的file descripter,1為stdout的file descripter[?],而2就是stderr了。[?]
因此I/O重導的真正格式為:
M<N M>N其中M為file descripter,N為某個檔案[?]。而如果要把fd導向給另一個fd,就要用下列格式:
M>&N其中M和N都是file descripter。
然而依然要小心一個小問題,就是重導的次序不同,效果也會有不同。
考慮以下的狀況:
因為第一種寫法,代表stdout先被dup2到output.txt,然後stderr才被dup2到被更改過的stdout,因此兩個都會進入output.txt。
而第二種寫法,則是stderr dup2到stdout,這時stdout還是連接在console上,不管之後stdout有沒有被更動,它就是會輸出到console,所以會變成stderr > console,stdout > output.txt。
考慮以下的狀況:
$ cat > test.c #include <stdio.h> int main( int argc, char * argv[] ) { puts( "This is stdout." ); fputs( stderr, "This is stderr." ); return 0; } ^D $ gcc test.c -o test $ ./test >output.txt 2>&1 $ ./test 2>&1 >output.txt有趣的是,第一次在螢幕上什麼都沒顯示,而output.txt裡會找到那二個句子,但是第二次卻會在螢幕上顯示`This is stderr.',output.txt只有`This is stdout.'。表面看起來結果至少要相反才對呀?
因為第一種寫法,代表stdout先被dup2到output.txt,然後stderr才被dup2到被更改過的stdout,因此兩個都會進入output.txt。
而第二種寫法,則是stderr dup2到stdout,這時stdout還是連接在console上,不管之後stdout有沒有被更動,它就是會輸出到console,所以會變成stderr > console,stdout > output.txt。
沒有留言:
張貼留言