1.介紹 linux
IO重定向用於捕捉一個文件,命令,程序,腳本或者代碼塊的輸出,而後把捕捉到的輸出做爲輸入發送給另一個文件,命令,程序或腳本。shell
終端程序通常從單一源以流的形式彙集輸入和顯示輸出,script執行時(進程), 系統會默認開啓3個標準文件,stdin, stdout,stderr . script默認會由stdin讀取數據,默認指鍵盤,由stdout輸出執行結果,默認指屏幕; 如有錯誤發生,則由stderr顯示信息,默認也指向屏幕。系統開啓這3個文件時,以文件代碼(分別爲0,1,2)做爲鏈接,這三個文件被稱爲標準I/O.Linux Shell 環境中支持標準輸入輸出重定向,用符號<和>來表示,故能夠用來指定須要重定向的標準輸入或輸出,好比 2>a.txt 表示將錯誤信息輸出到文件a.txt中。bash
同時,還能夠在這三個標準輸入輸出之間實現重定向,好比將錯誤信息重定向到標準輸出,能夠用 2>&1來實現。經常使用的用法之一是將輸出重定向至 /dev/null 來禁止輸出。網絡
2. file descriptor FD ide
進程必須先打開一個文件,才能讀取或寫入文件,Linux進程經過給每一個當前被打開的文件賦整數值(從0開始)來追蹤文件,這個整數被稱爲文件描述符,以後對此文件的操做都使用FD來完成。Linux經過/proc 文件系統來檢查當前運行進程打開的文件和文件描述符/proc/pid/fd,pid 即對應進程ID,fd 文件夾下以整數文件描述符命名的符號連接,連接到打開文件自己。函數
每個I/O管道被用一個整數命名,文件描述符能夠與常規文件、設備節點、網絡套接字鏈接(即在虛擬文件系統/proc中,以數字命令的連接文件,連接到指定文件)。測試
其中0,1,2三個特殊的FD,就是STDIN,STDOUT,STDERR,分別指向相應的設備文件this
標準輸入STDIN:程序讀取的源url
標準輸出STDOUT:程序寫入的目的地spa
標準錯誤STDERR:程序將出錯情況報告給一個叫標準錯誤stderr 的目的地
|
FD |
默認輸出位置 |
重定向操做符 |
STDIN |
0 |
keyboard input |
(0)< (0)<< |
STDOUT |
1 |
mointor |
(1)> (1)>> |
STDERR |
2 |
monitor |
2> 2>> |
3. Pipeline and redirection
Pipe將多個命令鏈接在一塊兒,是Linux的一種基本的進程間通訊技術。它的設計符合Unix哲學:複雜的系統應該由簡單的、專門的、互操做簡單的組件構成,故許多標準Linux程序被設計爲過濾器。
管道:把一個進程的標準輸出流與另外一個進程的標準輸入流鏈接起來,管道符|用於鏈接一個命令的標準輸出與另外一條命令的標準輸入
pipe 命令:pipe 後面接的第一個數據一定是指令,且這個指令必須可以接受stdin 數據並處理, pipe 命令僅處理stdout , 而忽略stderr ,並將處理結果傳遞給標準輸出,如grep , head, tail, cut, sort, expand,sed,awk,fmt,tac,tr,grep,nl,pr , sed ,awk
過濾器(filters):用來接收標準輸入,通過過濾器命令的轉化,再寫到標準輸出。如cat test | grep ade| tac 中|grep| 即爲過濾器
4. 重定向
即不使用系統默認的標準輸入輸出,而是從新指定,即輸入重定向,輸出重定向,錯誤輸出重定向,
雙重輸出重定向(一次單獨地送到不一樣的地方)。IO重定向其實就是讓已建立的FD指向其它的文件(修改其連接的文件)。輸入輸出數據流的位置用FD標識。
IO重定向的原理就是經過exec 來操做FD(修改FD所指向的文件),來實現將輸入和輸出設定爲指定的文件(或設備)。關於重定向須要注意:
基本IO重定向
cmd > file 把 stdout 重定向到 file 文件中;
cmd 1> file 同上
cmd >> file 把 stdout 重定向到 file 文件中(追加);
cmd 2> file 把 stderr 重定向到 file 文件中;
cmd 2>> file 把 stderr 重定向到 file 文件中(追加);
cmd > file 2>&1 把 stderr和 stdout 一塊兒重定向到 file 文件中;
cmd &>file 上一例的簡寫形式
cmd >> file 2>&1 把 stderr 和 stderr 一塊兒重定向到 file 文件中(追加);
cmd >/dev/null 2>/dev/null 不記錄標準輸出或標準錯誤輸出
cmd &>/dev/null 同上
cmd < file cmd 命令以 file 文件做爲 stdin;
cmd < file >file2 cmd 命令以 file 文件做爲 stdin,以 file2 文件做爲 stdout;
cmd << delimiter Here document,從 stdin 中讀入,直至遇到 delimiter 分界符。
示例說明
find / -name 2>/dev/null
date>file1 標準輸出無內容,file1中有內容。(先執行重定向)
(date)>file1 標準輸出無內容,file1中有內容。(先將子shell 標準輸出重定向至file1)
(date >file1) >file2 file1中有內容,file2中無內容。(將子shell 標準輸出重定向至file2;子shell中,date標準輸出重定向至file1,子shell標準輸出沒有內容,file1中有內容)
date >file1 >file2 file1中無內容,file2中有內容。(將date 標準輸出重定向至file1,而後再將date標準輸出重定向至file2,都是針對同一個文件描述符,會覆蓋.
> test.txt 新建空白文件,或者清空文件(危險命令), 多用於清空日誌
> /dev/sda
會致使整個塊設備的數據丟失
5. IO重定向符號彙總
cmd n>file |
將FD爲n的輸出寫入file |
cmd >file |
標準輸出寫入file中 FD爲1,即將標準輸出重定向到file > 爲1>的簡寫形式 |
cmd n<file |
將file讀入到FD n中 |
cmd <file |
將file 讀入標準輸入中 FD爲0, 即將標準輸入重定向到file < 爲0<的簡寫形式 |
cmd n>>file |
將FD爲n的輸入追加寫入到file |
cmd >>file |
追加輸出至file中,FD爲1 |
cmd >|file |
忽略shell的noclobber選項,強制覆蓋file |
cmd n>|file |
忽略noclobber選項(shell選項),強制將FD爲n的輸出寫入file |
cmd n>>|file |
忽略noclobber選項 |
<<delimiter |
|
cmd1 | cmd2 |
管道符|(特殊IO重定向), 將cmd1的標準輸出做爲cmd2的標準輸入 |
5.腳本中臨時重定向每一行
此方法能夠爲生成錯誤消息提供方便
cat retest.sh
#!/bin/bash
echo "this is an error" >&2 #重定向至指定FD,此處重定向至標準錯誤輸出
echo "this is normal output"
echo "redirect this line to standard output" >&1
[ade@h test]$ ./test.sh >test1 2>test2
[ade@h test]$ cat test1
this is normal output
redirect this line to standard output
[ade@h test]$ cat test2
this is an error
7. 腳本中代碼塊重定向
代碼重定向是指在代碼塊內將標準輸入或標準輸出重定向到文件,而代碼塊以外而保持默認狀態(即重定向只對代碼塊有效,而不是整個腳本),它可讓代碼塊方便的處理一個文件,它也是腳本中的臨時重定向,特別之處是它針對的是shell腳本中相應的結構代碼。
while,until,for,if/then, 函數等代碼塊均可以使用重定向,<輸入重定向,>輸出重定向。
cat rewhile.sh
#!/bin/bash
ls /etc > loggg
while [ "$filename" != "rc.d" ]
do
read filename
let "count +=1"
done < loggg
echo "$count times read"
#測試循環體外的標準輸入是否被重定向
echo -n " ------pls input data:---------"
read test
echo $test
cat reif.sh
if [ -z "$1" ]
then
echo "positional parameter is null"
fi > loggg
echo "-----------Normal stdout--------"
其它結構的重定向
for
do
......
done < loggg
if [condition]
then
...
else
...
fi < loggg
until [condition]
do
...
done < loggg
8. 腳本中永久重定向全部命令
當但願將腳本中的不少輸出都重定向時,可使用exec 通知shell在腳本執行時重定向特定的文件描述符。實例上是使用exec 來完成FD的相關操做。
cat test1.sh
#!/bin/bash
exec 1>testout
echo "line one"
echo "line two"
echo "line three"
cat test.sh
#!/bin/bash
exec 2>testerr
echo "this is the start of the script"
echo "the following command will redirect all ouptput to testout"
exec 1> testout #or exec > testout
echo " put this line into testout"
echo "put this line into testerr" >&2
[ade@h test]$ ./test.sh
this is the start of the script
the following command will redirect all ouptput to testout
[ade@h test]$ cat testout
put this line into testout
[ade@h test]$ cat testerr
put this line into tester
refer
man bash here documents 部分
awk, fold, grep, head, nnkf, pr, sed, sort, tail, tee, tr, uniq, wc
lsof : 列出全部開放的文件描述符