????????數據流重定向(redirect)由字面上的意思來看,好像就是將【數據給它定向到其他地方去】的樣子?
????????沒錯,數據流重定向就是將某個命令執行后應該要出現在屏幕上的數據,給它傳輸到其他的地方,例如文件或是設備(例如打印機之類的)。
????????這玩意兒在Linux的命令行模式下面很重要,尤其是如果我們想要將某些數據存儲下來時,就更有用了。
1.什么是數據流重定向
什么是數據流重定向?這得要由命令的執行結果談起。
一般來說,如果你要執行一個命令,通常它會是這樣的:
我們執行一個命令的時候,這個命令可能會由文件讀入數據,經過處理之后,再將數據輸出到屏
幕上。
在上圖當中,standard output 與standard error output分別代表【標準輸出(STDOUT)】與【標準錯誤輸出(STDERR)】,這兩個玩意兒默認都是輸出到屏幕上面來的
那么什么是標準輸出與標準錯誤輸出?
????????簡單地說,標準輸出指的是命令執行所返回的正確信息,而標準錯誤輸出可理解為命令執行失敗后,所返回的錯誤信息。
舉個簡單例子來說,
我們的系統默認有/etc/crontab但卻無/etc/birdsay,此時若執行【cat /etc/crontab? ?/etc/vbirdsay】這個命令時,cat會進行:
- 標準輸出:讀取/etc/crontab后,將該文件內容顯示到屏幕上;
- 標準錯誤輸出:因為無法找到/etc/vbirdsay,因此在屏幕上顯示錯誤信息;
不管正確或錯誤的數據都是默認輸出到屏幕上,所以屏幕當然是亂的。
那能不能通過某些機制將這兩股數據分開?
當然可以,那就是數據流重定向的功能,數據流重定向可以將standard output(簡稱stdout)與standard error output(簡稱stderr)分別傳送到其他的文件或設備,而分別傳送所用的特殊字符則如下所示:
- 標準輸入(stdin):代碼為0,使用<或<<;
- 標準輸出(Stdout):代碼為1,使用>或>>;
- 標準錯誤輸出(stderr):代碼為2,使用2>或2>>;
2.標準輸出流重定向
什么是標準輸出重定向?
輸出重定向:指的是重新指定設備來代替顯示器作為新的輸出設備。
2.1.?>
[root@zaishu ~]# ls -l > x 不輸出到屏幕,輸出到文本,這就是輸出重定向;另外當指定沒有描述符的時候,默認就是標準數據流。
root@zaishu ~]# ls -l 1> x (這兩條命令的效果一樣 1就是代表標準輸出流)
范例一:觀察你的系統根目錄(/)下各目錄的文件名、權限與屬性,并記錄下來
此時屏幕會顯示出文件名信息
屏幕并無任何信息
有個新文件被建立了。
我們打開看看
怪了,屏幕怎么會完全沒有數據?這是因為原本【ll /】所顯示的數據已經被重定向到~/rootfile文件中了,這個~/rootfile的文件名可以隨便你取。
如果你執行【cat ~/rootfile】那就可以看到原本應該在屏幕上面的數據。
如果我再次執行:【ll /home > ~/rootfile】后,這個~/rootfile文件的內容變成什么呢?
?它將變成【僅有ll? /home的數據】而已。咦?原本的【ll? /】數據就不見了嗎?
是的,因為該文件的建立方式是:
- 該文件(本例中是~/rootfile)若不存在,系統會自動地將它建立起來。
- 當這個文件存在的時候,那么系統就會先將這個文件內容清空,然后再將數據寫入。
- 也就是若以>輸出到一個已存在的文件中,這個文件就會被覆蓋掉。
2.2.? >>?
那如果我想要將數據累加而不想要將舊的數據刪除,那該如何是好?
利用兩個大于的符號(>>)就好。
以上面的范例來說,你應該要改成【ll? >> ~/rootfile】即可。
如此一來,當
- (1)~/rootfile不存在時系統會主動建立這個文件;
- (2)若該文件已存在,則數據會在該文件的最下方累加進去。
我們接著上面那個例子來講講
來總結一下
3.標準錯誤流重定向?
上面談到的是標準輸出的正確數據,那如果是標準錯誤的錯誤數據?
那就通過2>及2>>,同樣是覆蓋(2>)與累加(2>>)的特性。
?stdout代碼是1而 stderr代碼是2,所以這個2>是很容易理解的,而如果僅存在>時,則代表默認的代碼1,也就是說:
- 1>:以覆蓋的方法將【正確的數據】輸出到指定的文件或設備上;
- 1>>:以累加的方法將【正確的數據】輸出到指定的文件或設備上;
- 2>;以覆蓋的方法將【錯誤的數據】輸出到指定的文件或設備上;
- 2>>;以累加的方法將【錯誤的數據】輸出到指定的文件或設備上;
要注意,【1>>】以及【2>>】中間是沒有空格的,
OK,有些概念之后讓我們繼續聊一聊這家伙怎么應用吧!
????????當你以一般身份執行find這個命令的時候,由于權限的問題可能會產生一些錯誤信息
例如執行【find /home?-name testing】時,可能會產生類似【find:/root:Permission denied】之類的信息,例如下面這個范例:
????????范例二:利用一般身份賬號查找/home下面是否有名為,bashrc的文件存在.
????????下面還有我們之前建立的賬號存在,這些賬號的根目錄你當然不能進入,所以就會有錯誤及正確數據,好了,
????????那么假如我想要將數據輸出到 list 這個文件中?
執行【find /home -name.bashrc > list】會有什么結果?
?????????呵呵,你會發現 list 里面存了剛剛那個【正確】的輸出數據,至于屏幕上還是會有錯誤的信息出現,傷腦筋。
????????如果想要將正確的與錯誤的數據分別存入不同的文件中需要怎么做?
范例三:承范例二,將stdout與stderr分別存到不同的文件中
????????注意,此時屏幕上不會出現任何信息。因為剛剛執行的結果中,有Permission 的那幾行錯誤信息都會跑到 list_error 這個文件中,至于正確的輸出數據則會存到 list_right 這個文件中。
????????這樣可以了解了嗎?如果有點混亂的話,去休息一下再回來看看吧!
4./dev/null 垃圾桶黑洞設備與特殊寫法
想象一下,如果我知道錯誤信息會發生,所以要將錯誤信息忽略掉而不顯示或存儲?
這個時候黑洞設備/dev/nul 就很重要了,這個/dev/nul可以吃掉任何導向這個設備的信息。
將上述的范例自定義
范例四:承范例三,將錯誤的數據丟棄,屏幕上顯示正確的數據.
只有 stdout 會顯示到屏幕上,stderr 被丟棄了
再想象一下,如果我要將正確與錯誤數據通通寫入同一個文件中?
這個時候就得要使用特殊的寫法了。我們同樣用下面的案例來說明:
范例五:將命令的數據全部寫入名為list 的文件中
錯誤 ,由于兩股數據同時寫入一個文件,又沒有使用特殊的語法,此時兩股數據可能會交叉寫入該文件內,造成次序的錯亂。所以雖然最終 list文件還是會產生,但是里面的數據排列就會怪怪的,而不是原本屏幕上的輸出排序。
?正確?
?正確
????????至于寫入同一個文件的特殊語法如上表所示,你可以使用2>&1也可以使用&>
4.1.&(重點)
& 是一個描述符,如果在1和2前面不加&,這個時候1和2表示的是普通文件。加了&表示的是重定向到對應的設備。 舉例:
- 1>&2 意思是把標準輸出重定向到標準錯誤,如果是 1>2 ?表示的是將標準輸出重定向到2這個文件。
- 2>&1 意思是把標準錯誤輸出重定向到標準輸出。如果是 2>1 ?表示的是將標準錯誤重定向到1這個文件
- &>filename 意思是把標準輸出和標準錯誤輸出都重定向到文件filename中
5.standard input :<與<<
輸入重定向:指的是重新指定設備來代替鍵盤作為新的輸入設備;
了解了stder與stdout后,那么那個<又是什么呀?
呵呵,以最簡單的語法來說,那就是【將原本需要由鍵盤輸入的數據,改由文件內容來替換】的意思。
5.1.cat
我們先由下面的cat 命令操作來了解一下什么叫做鍵盤輸入吧!
范例六:利用cat命令來建立一個文件的簡單流程。
執行后我們輸入一些東西
這里按下[ctrl]+d來退出。
由于加入>在cat后,所以這個catfile會被主動地建立,而內容就是剛剛鍵盤上面輸入的那兩行數據了。
唔,那我能不能用純文本文件替換鍵盤的輸入,也就是說,用某個文件的內容來替換鍵盤的敲擊?可以的,如下所示:
范例七:用stdin替換鍵盤的輸入以建立新文件的簡單流程。
注意看,這兩個文件的大小會一模一樣,幾乎像是使用cp來復制一般。
????????這東西非常有幫助,尤其是用在類似mail這種命令的使用上。
理解<之后,再來則是怪可怕的<< 這個連續兩個小于的符號了,它代表的是【結束的輸入字符】的意思。
舉例來講:我要用cat直接將輸入的信息輸出到catfile中,且當由鍵盤輸入eof時,該次輸入就結束,那我可以這樣做:
輸入eof這關鍵詞,立刻就結束而不需要輸入[ctrl]+d。且文件里只有這兩行,不會存在關鍵詞那一行
看到了嗎?利用<<右側的控制字符,我們可以終止一次輸入,而不必按下[crtl]+d來結束,這對程序寫作很有幫助。
5.2.<,<<
[root@zaishu ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
saslauth:x:998:76:Saslauthd user:/run/saslauthd:/sbin/nologin
oracle:x:1002:1002::/home/oracle:/bin/bash
[root@zaishu ~]# cat < /etc/passwd //將passwd內容輸給cat,cat然后將內容輸出到屏幕
root:x:0:0:root:/root:/bin/bash
...
saslauth:x:998:76:Saslauthd user:/run/saslauthd:/sbin/nologin
oracle:x:1002:1002::/home/oracle:/bin/bash
?例2. 分界符
[root@zaishu ~]# cat << 0 //遇到0,表示跳出
> a
> b
> c
> 0
a
b
c
例3. 輸入 輸出一起用
通過重定向 將/etc/passwd 作為輸入設備,并輸出重定向到 shu.txt,最終實現將 /etc/passwd 文件中內容復制到 shu.txt 。
[root@prometheus ~]# cat < /etc/passwd > shu.txt
[root@prometheus ~]# cat shu.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
prometheus:x:998:996::/home/prometheus:/bin/bash
node_exporter:x:997:995::/home/node_exporter:/bin/bash
?6.為何要使用命令輸出重定向?
好了,那么為何要使用命令輸出重定向?
我們來說一說吧!
- 屏幕輸出的信息很重要,而且我們需要將它存下來的時候;
- 后臺執行中的程序,不希望它干擾屏幕正常的輸出結果時;
- 一些系統的計劃任務命令(例如寫在/etc/crontab中的文件)的執行結果,希望它可以存下來時;
- 一些執行命令的可能已知錯誤信息時,想以【2>? /dev/null】將它丟掉時;
- 錯誤信息與正確信息需要分別輸出時。
·當然還有很多的功能,最簡單的就是網友們常常問到的:為何我的root 都會收到系統crontab傳來的錯誤信息?
這個東西是常見的錯誤,而如果我們已經知道這個錯誤信息是可以忽略的時候,嗯,【2> errorfile】這個功能就很重要了。了解了嗎?
例題
問:? 假設我要將echo "error message”以標準錯誤的格式來輸出,該如何處置?
答:
既然有2>&1來將2>轉到1>去,那么應該也會有1>&2吧?????????沒錯,就是這個概念,因此你可以這樣做:
- [dmtsai@study -]$?echo "error message" 1>&2
- [dmtsai@study -]$?echo "error message" 2> /dev/null 1>&2
你會發現第一條有信息輸出到屏幕上,第二條則沒有信息,這表示該信息已經通過2>/dev/null丟到垃圾桶中了,可以肯定是錯誤信息。