首頁 > 軟體

Linux 輸入輸出(I/O)重定向

2020-06-16 17:35:23

1、概念

在解釋什麼是重定向之前,先來說說什麼是檔案描述符

Linux 檔案描述符

檔案描述符可以理解為 Linux 系統為檔案分配的一個數位,範圍是 0-3 ,使用者也可以自定義檔案描述符,但是自定檔案描述符不在這裡的討論範圍

檔案描述符(file descriptor)

名稱型別檔案描述符操作
標準輸入 standard input 0 <,<<
標準輸出 standard output 1 >,>>
標準錯誤輸出 standard error output 2 2>,2>>

檔案描述符的儲存位置位於 /proc/self/fd ,檔案描述符是通過一系列軟連結指向的預設輸出裝置,這裡我們的預設裝置就是模擬終端

模擬終端的檔案可以使用命令 tty 來檢視

[divent@bash]$ ls -al /proc/self/fd
total 0
lrwx------. 1 divent divent 64 Aug 15 14:09 0 -> /dev/pts/0
lrwx------. 1 divent divent 64 Aug 15 14:09 1 -> /dev/pts/0
lrwx------. 1 divent divent 64 Aug 15 14:09 2 -> /dev/pts/0

對於一條 Linux 的命令執行的過程如下

  1. 使用者開始從鍵盤(鍵盤在 Linux 上屬於檔案)輸入資料,也就是系統從檔案中讀取資料的時候
  2. shell 將接受到的資料(標準輸入)傳遞給相應的命令開始執行
  3. (yes)執行成功後,即可獲得標準正確輸出。(no)執行失敗後,獲得標準錯誤輸出
  4. 在預設情況下,標準正確輸出的結果與標準錯誤輸出的預設輸出都為當前使用者執行的終端

一個命令執行以前,會準備好所有的輸入輸出,預設分別系結 stdin(0),stdout(1),stderr(2)。如果在準備命令的時候出現錯誤,那麼這個命令將不會執行


2、輸出重定向

格式

command [OPTION]{>,>>} [File]
option:
    1   standard output(default)
    2   standard error output
    &   all output

> 為覆蓋輸出,>>為追加輸出

範例

#假設當前資料夾有檔案 test2 
[divent@bash]$ ls test test2
ls: cannot access test: No such file or directory
test2

這裡可以看到同時擁有的標準輸出與標準錯誤輸出都顯示在了螢幕上
現在我們要將輸出寫入到檔案中

#假設已經有檔案 test2 , test3
[divent@bash]$ ls test test2 > test3
ls: cannot access test: No such file or directory
[divent@bash]$ cat test3
test2

因為這裡的檔案只預設接受了標準輸出,所以標準錯誤輸出就輸出到了終端上
我們也可以將標準錯誤輸出寫入到檔案

#假設已經有檔案 test2 , stderr
[divent@bash]$ ls test test2 2> stderr
test2
[divent@bash]$ cat stderr
ls: cannot access test: No such file or directory

這裡獲得的結果就和剛剛的結果正好相反
我們也可以將標準輸出與標準錯誤輸出都重定向到不同的檔案

#假設已經有檔案 test2 , stdout , stderr
[divent@bash]$ ls test test2 1> stdout 2>stderr
[divent@bash]$ cat stdout
test2
[divent@bash]$ cat stderr
ls: cannot access test: No such file or directory

這裡我們就將兩個不同的輸出輸出到了指定的檔案中
我們也可以將兩個輸出同時輸出到同一個檔案中

#假設已經有檔案 test2 , test3
[divent@bash]$ ls test test2 &> test3
[divent@bash]$ cat test3
ls: cannot access test: No such file or directory
test2

這裡就使用 & 將兩種輸出同時輸出到了同一個檔案
我們也可以只接受某一種輸出,而將其他的輸出導向到其他地方

#假設已經有檔案 test2 
[divent@bash]$ ls test test2 2>&-
test2
[divent@bash]$ ls test test2 2>/dev/null
test2
# &- 意義為關閉這個輸出,/dev/null 是 linux 的黑洞裝置

注意

  • shell遇到 > 操作符,會判斷右邊檔案是否存在,如果存在就先刪除,並且建立新檔案。不存在直接建立。 無論左邊命令執行是否成功。右邊檔案都會變為空。
  • >> 操作符,判斷右邊檔案是否存在,如果不存在,先建立。以新增方式開啟檔案,會分配一個檔案描述符[不特別指定,預設為1]然後,與左邊對應的輸出系結。
  • 一條命令在執行前,先會檢查輸出是否正確,如果輸出裝置錯誤,將不會進行命令執行

3、輸入重定向

格式

command {<} [File] {<<} [Word]

這裡的 <<< 意義不是類似於輸出重定向的操作符,< 是從檔案中取出資料到指定的檔案中

範例

[divent@bash]$ cat > newfile
123
abc
456
[divent@bash]$cat newfile
123
abc
456
#這裡使用 Ctrl + D 可以結束輸入,從鍵盤輸入的資料會儲存存到 newfile 檔案中

cat 命令直接使用的話可以直接接收鍵盤的輸入

現在來嘗試從檔案中輸入

#這裡的範例我們使用剛才建立的 test3 檔案
[divent@bash]$ cat test3
ls: cannot access test: No such file or directory
test2
[divent@bash]$ cat > newfile < test3
[divent@bash]$ cat newfile 
ls: cannot access test: No such file or directory
test2

這裡的先將檔案中的資料提取到了命令 cat 中 ,然後由 cat 寫入到 newfile


4、自定義輸入輸出裝置

解釋

除了使用系統給你定義的檔案描述符以外,使用者還可以自己自定義檔案描述符,首先使用 ulimit -n 來檢視檔案描述符的上限,然後使用命令 exec 來為一個檔案新增檔案描述符

範例

#首先檢視一下現在已經被佔用的檔案描述符
[divent@bash]$ ls /proc/self/fd
0   1   2   3

#這個時候我們可以使用 exec 命令來為一個檔案賦予一個檔案描述符
[divent@bash]$ touch /tmp/test && exec 5>/tmp/test

#然後我們再檢視檔案描述符 5
[divent@bash]$ ls -al /proc/self/fd/5
l-wx------. 1 divent divent 64 Aug 15 14:54 /proc/self/fd/5 -> /tmp/test

#現在我們使用自己自定義的檔案描述符來重定向輸出
[divent@bash]$ ls -l /etc >&5

#然後我們再來檢視檔案中的資料, 因為檔案中有資料,這裡就只取出前 5 行作為範例
[divent@bash]$ head -n 5 /tmp/test
total 1936
drwxr-xr-x.  3 root root     4096 Jun 10 22:12 abrt
-rw-r--r--.  1 root root       16 Jun  9 16:56 adjtime
-rw-r--r--.  1 root root     1518 Feb 22 22:11 aliases
drwxr-xr-x.  2 root root     4096 Jun 10 22:11 alsa

#我們也可以使用 exec 來將檔案的預設輸出指向檔案
[divent@bash]$ exec 1>&5
[divent@bash]$ ls -l /etc
#這個時候就會發現沒有輸出了,已經輸出內容已經到了 /tmp/test 中了

#如果想要恢復輸出,將預設輸出重新指向當前 /dev/pts/0 即可
[divent@bash]$ exec 1>/dev/pts/0

#關閉檔案描述符
[divent@bash]$ exec 5>&-

#最後我們檢視一下
[divent@bash]$ ls /proc/self/fd
0  1  2  3

最後說兩句

  • 如果不是很好理解的話,一定要貫徹 Linux 一切皆檔案的理念,檔案描述符最終也是指向的是檔案
  • 使用自己自定義的描述符可以簡化一些備份之類的任務
  • 在 shell 指令碼中,輸入輸出重定向是經常使用的

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-08/134294.htm


IT145.com E-mail:sddin#qq.com