Shell重定向與exec


前言

  首先我們需要知道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 號輸出關閉
述所有形式都可以前導一個數字,此時建立的文件描述符由這個數字指定而不是缺省的 01。如:


... 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將其打開。
  • 我想:他們的不同點在於:
  1. cmd >a 2>a 相當於使用了兩個互相競爭使用文件a的管道;

  2. 而cmd >a 2>&1 只使用了一個管道,但在其源頭已經包括了stdout和stderr。

  3.  

    從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


免責聲明!

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



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