前言
首先我們需要知道exec是什么,exec是linux下面一個創建進程的方法,詳情請參考:https://www.cnblogs.com/guge-94/p/11016176.html
重定向
概念
- I/O重定向通常與FD有關
- 三個常用FD(默認與keyboard、monitor、monitor有關)
- 一般情況下,操作系統默認只存在這三個fd,但是我們通過ls去查看的時候發現會有一個大於2的fd,這是因為我們在查看的時候會有一個句柄產生,這個時候會生成一個新的fd
FD | 說明 |
---|---|
0 | stdin,標准輸入 |
1 | stdout,標准輸出 |
2 | stderr,標准錯誤輸出 |
查看文件描述符
ll /proc/$$/fd
重定向輸出
&- 關閉標准輸出 n&- 表示將 n 號輸出關閉 述所有形式都可以前導一個數字,此時建立的文件描述符由這個數字指定而不是缺省的 0 或 1。如: ... 2>file 運行一個命令並把錯誤輸出(文件描述符 2)定向到 file。 ... 2>&1 運行一個命令並把它的標准輸出和輸出合並。(嚴格的說是通過復制文件描述符 1 來建立文件描述符 2 ,但效果通常是合並了兩個流。) 我們對 2>&1詳細說明一下 : 2>&1 也就是 FD2=FD1 ,這里並不是說FD2 的值等於FD1的值,因為 > 是改變送出的數據信道,也就是說把 FD2 的 “數據輸出通道” 改為 FD1 的 “數據輸出通道”。 如果僅僅這樣,這個改變好像沒有什么作用,因為 FD2 的默認輸出和 FD1 的默認輸出本來都是 monitor,一樣的!但是,當 FD1 是其他文件,甚至是其他 FD 時,這個就具有特殊的用途了。請大家務必理解這一點。
重定向恢復
如果 stdin, stdout, stderr 進行了重定向或關閉, 但沒有保存原來的 FD, 可以將其恢復到 default 狀態嗎?
如果關閉了stdin,因為會導致退出,那肯定不能恢復。
如果重定向或關閉 stdout和stderr其中之一,可以恢復,因為他們默認均是送往monitor(但不知會否有其他影響)。
如果恢復重定向或關閉的 stdout: exec 1>&2
,恢復重定向或關閉的stderr:exec 2>&1
。
如果stdout和stderr全部都關閉了,又沒有保存原來的FD,可以用:exec 1>/dev/tty
恢復。
cmd >a 2>a 和 cmd >a 2>&1 為什么不同?
- cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件會被打開兩遍,由此導致stdout和stderr互相覆蓋。
- cmd >a 2>&1 :stdout直接送往文件a ,stderr是繼承了FD1的管道之后,再被送往文件a 。a文件只被打開一遍,就是FD1將其打開。
- 我想:他們的不同點在於:
-
cmd >a 2>a 相當於使用了兩個互相競爭使用文件a的管道;
-
而cmd >a 2>&1 只使用了一個管道,但在其源頭已經包括了stdout和stderr。
-
從IO效率上來講,cmd >a 2>&1的效率應該更高!
常用命令語法
exec 1>outfilename # 打開文件outfilename作為stdout exec 2>errfilename # 打開文件errfilename作為 stderr exec 1&- # 關閉 FD1 exec 5>&- # 關閉 FD5 exec 4<&1 # 備份當前stdout至FD4 exec 1>1.txt # stdout重定向至1.txt exec 1<&4 # 恢復stdout exec 4>&- # 關閉 FD4 exec 6>&1 # 將標准輸出與fd 6綁定 exec 1>&6 # 將標准輸出1恢復回來
示例
exec 1>&- 2>&- # 關閉所有的輸出
重定向輸入
格式
command-line [n]<file或文件描述符&設備
將命令默認從鍵盤獲得的輸入,改成從文件,或者其它打開文件以及設備輸入。執行這個命令,將標准輸入0,與文件或設備綁定。將由它進行輸入。
示例
實例一:用catfile文件里面的內容代替鍵盤輸出,輸出到屏幕。 [root@asus-a53s data]# cp suc.test catfile [root@asus-a53s data]# cat < catfile Ls #這里如果內容過多,按下 [ctrl]+d 離開 [root@asus-a53s data]# cat suc.test ls 實例二:從標准輸入【鍵盤】獲得數據,然后輸出給catfile文件 [root@asus-a53s data]# cat > catfile << EOF #EOF可以是任何字符,代表結束 > hello,This is my test! > EOF [root@asus-a53s data]# cat catfile #上面用的是重定向覆蓋,所以ls內容不見了 hello,This is my test! 實例三:從test.sh 獲得輸入數據,然后輸出給文件catfile [root@asus-a53s data]# cat test.sh 1 test1 test1 test1 [root@asus-a53s data]# cat > catfile < test.sh #這里在輸入的時候不能用<<,因為<<同時是也代表結束輸出 [root@asus-a53s data]# cat catfile 1 test1 test1 test1
綁定重定向
格式
exec 文件描述符[n] <或> file或文件描述符或設備 在上面講的輸入,輸出重定向 將輸入,輸出綁定文件或設備后。只對當前那條指令是有效的。如果需要在綁定之后,接下來的所有命令都支持的話。就需要用exec命令
示例
實例一:學習exec的綁定使用 [chengmo@centos5 shell]$ exec 6>&1 #將標准輸出與fd 6綁定 [chengmo@centos5 shell]$ ls /proc/self/fd/ 0 1 2 3 6 #出現文件描述符6 [chengmo@centos5 shell]$ exec 1>suc.txt #將接下來所有命令標准輸出,綁定到suc.txt文件(輸出到該文件) [chengmo@centos5 shell]$ ls -al #執行命令,發現什么都不返回了,因為標准輸出已經輸出到suc.txt文件了 [chengmo@centos5 shell]$ exec 1>&6 #恢復標准輸出 [chengmo@centos5 shell]$ exec 6>&- #關閉fd 6描述符 [chengmo@centos5 ~]$ ls /proc/self/fd/ 1 2 3
參考文檔:
http://xstarcd.github.io/wiki/shell/exec_redirect.html
https://www.cnblogs.com/chengmo/archive/2010/10/20/1855805.html