Linux 文件描述符詳解


Overview

了解Linux怎樣處理輸入和輸出是非常重要的。一旦我們了解其原理以后,我們就可以正確熟練地使用腳本把內容輸出到正確的位置。同樣我們也可以更好地理解輸入重定向和輸出重定向。

Linux標准文件描述符

文件描述符 縮寫 描述
0 STDIN 標准輸入
1 STDOUT 標准輸出
2 STDERR 標准錯誤輸出

Linux系統將所有設備都當作文件來處理,而Linux用文件描述符來標識每個文件對象。其實我們可以想象我們電腦的顯示器和鍵盤在Linux系統中都被看作是文件,而它們都有相應的文件描述符與之對應。

其實我們與計算機之間的交互是我可以輸入一些指令之后它給我一些輸出。那么我們可以把上面表格中的文件描述符0理解為我和計算機交互時的輸入,而這個輸入默認是指向鍵盤的; 文件描述符1理解為我和計算機交互時的輸出,而這個輸出默認是指向顯示器的;文件描述符2理解為我和計算機交互時,計算機出現錯誤時的輸出,而這個輸出默認是和文件描述符1指向一個位置;

就像我上面說的那樣,既然它們是默認的,我就可以更改它們。下面的命令就是把標准輸出的位置改到xlinsist文件中:

exec 1> xlinsist
   
   
  
 
 
         
  • 1

這回如果我輸入ls -al 或者ps命令,我們的終端將不會顯示任何東西。現在,我們可以新開一個終端查看xlinsist這個文件中是否有上面兩個命令所顯示的內容。注意:你必須新開一個終端。

同樣的道理,我們也可以改變標准輸入的位置。首先,我們先看看沒改變的樣子:

vincent@geek:~/test$ read user
xlinsist
vincent@geek:~/test$ echo $user
xlinsist
vincent@geek:~/test$
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5

也就是我們從鍵盤輸入把xlinsist讀入到user變量。這個read需要我輸入。現在,我要改變標准輸入的默認位置:

#我只是把當前的標准輸出重定向到test文件中
vincent@geek:~/test$ echo 'xlinsist' 1> test
vincent@geek:~/test$ cat test 
xlinsist
#我只是把當前的標准輸入重定向到test文件中
vincent@geek:~/test$ read user 0< test 
vincent@geek:~/test$ echo $user
xlinsist
vincent@geek:~/test$ 
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

從上面的read命令中可以看作,我並沒有被要求輸入什么。

標准錯誤輸出和標准輸出的區別是,它在命令出錯情況下的輸出。這沒有什么太大的不同,我們也可以把它的輸出修改到任何我們想要的位置。只不過我們需要把上面標准輸出的1改成2,命令如下:

exec 2> xlinsist
   
   
  
 
 
         
  • 1

當然,除了0, 1,2以外,我們可以分配自己的文件描述符。看下面的例子:

vincent@geek:~/test$ exec 6>test
vincent@geek:~/test$ echo 'i love linux shell!!!' 1>&6
vincent@geek:~/test$ cat test 
i love linux shell!!!
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4

上面的命令很有意思:我首先把文件描述符6指向test文件。因為不像描述符1,所有的輸出都會自然找它,然后看它是定向到顯示器還是某個文件。所以當我們想找描述符6的時候我們要用&來引用它。其實我們可以把文件描述符想像成一個文件的引用,它可以指向任何一個文件(包括顯示器),指向的過程就是我們修改默認位置的過程。而用&符號來找到它指向的目標文件,從而向其寫入數據。

如果你真正了解了上面的原理后,我們就可以隨便玩什么輸入重定向啊、輸出重定向啊,那都是小case。現在讓我們來個更加復雜的例子吧,來幫你們整理一下思路,腳本如下:

exec 3>&1
exec 1>test
echo "這句話被存到test文件中"
echo "還有這句"
exec 1>&3
echo "這句話輸出到顯示器"
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我們來一步一步理解上面的命令:首先文件描述符1默認指向的是顯示器,用&來找到文件描述符1指向的目標文件,也就是顯示器。因此文件描述符3也指向了顯示器。然后,我們修改了文件描述符1指向的文件到test文件。接着兩個echo命令的輸出會自然去找文件描述符1,然后它看到文件描述符1指向的是test文件,所以它會把輸出寫到test文件中。最后,我們用&來找到文件描述符3指向的目標文件,也就是顯示器,然后我們修改了文件描述符1指向的文件到顯示器。因此,最后一個echo命令會自然的找文件描述符1然后輸出到顯示器上。

整個過程就是這樣的,只要你理解了它們的原理,以后無論在腳本中怎樣處理重定向的你都不會感覺到迷茫了。下面我將介紹一些與文件描述符相關的一些shell命令,這可以讓你如虎添翼。

文件描述符相關的一些shell命令

lsof -a -p $$ -d 0,1,2

#下面為這個命令的輸出
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    22609 vincent    0u   CHR 136,13      0t0   16 /dev/pts/13
bash    22609 vincent    1u   CHR 136,13      0t0   16 /dev/pts/13
bash    22609 vincent    2u   CHR 136,13      0t0   16 /dev/pts/13
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

下圖是上面各項的含義

Linux 文件描述符詳解

現在我用下面命令修改其標准錯誤輸出:

vincent@geek:~/test$ exec 1> test 
vincent@geek:~/test$ lsof -a -p $$ -d 0,1,2

#新開一個終端,查看test文件,輸出如下
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    23061 vincent    0u   CHR 136,20      0t0     23 /dev/pts/20
bash    23061 vincent    1w   REG    8,2        0 525789 /home/vincent/test/test
bash    23061 vincent    2u   CHR 136,20      0t0     23 /dev/pts/20
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

/dev/null文件,這是一個很特殊的文件,你寫入的任何東西都會清空。大家可以向里面寫入數據試試效果。

  1. 我們可以把標准錯誤輸出重定向到/dev/null,從而丟掉不想保存的錯誤信息
  2. 我們可以快速移除現有文件的數據而不用先刪除文件在創建。命令如下:
cat /dev/null > test
   
   
  
 
 
         
  • 1

Linux使用/tmp目錄來存放不需要一直保留的文件,大多數Linux系統會在啟動時自動刪除/tmp目錄中所有的文件。

下面的命令可供使用:

# 文檔說文件的末尾必須至少包含3個'X',這個是在當前目錄創建的
mktemp test.XXX
# 這個是在/tmp目錄創建的
mktemp -t test.XXXXX
# 創建目錄,在當前目錄
mktemp -d test.XXXXX
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

tee命令 – 從標准輸入讀取,寫到標准輸出和文件。

# 把date產生的輸出寫到標准輸出和文件
date | tee test
# 追加數據
date | tee -a test
   
   
  
 
 
         
  • 1
  • 2
  • 3
  • 4

管道和重定向之間的區別

管道是把一個程序的輸出作為另一個程序的輸入。 
重定向是把輸出定向到文件或者標准流。

這有2個非常詳細的參考資料:

1、http://askubuntu.com/questions/172982/what-is-the-difference-between-redirection-and-pipe

2、http://ryanstutorials.net/linuxtutorial/piping.php

最好是先看第二個鏈接


轉自:http://blog.csdn.net/xlinsist/article/details/51147212


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM