shell的內建命令exec將並不啟動新的shell,而是用要被執行命令替換當前的shell進程,並且將老進程的環境清理掉,而且exec命令后的其它命令將不再執行。
因此,如果你在一個shell里面,執行exec ls;那么,當列出了當前目錄后,這個shell就自己退出了,因為這個shell進程已被替換為僅僅執行ls命令的一個進程,執行結束自然也就退出了。為了避免這個影響我們的使用,一般將exec命令放到一個shell腳本里面,用主腳本調用這個腳本,調用點處可以用bash a.sh,(a.sh就是存放該命令的腳本),這樣會為a.sh建立一個sub shell去執行,當執行到exec后,該子腳本進程就被替換成了相應的exec的命令。source命令或者”.”,不會為腳本新建shell,而只是將腳本包含的命令在當前shell執行。不過,要注意一個例外,當exec命令來對文件描述符操作的時候,就不會替換shell,而且操作完成后,還會繼續執行接下來的命令。
exec 3<&0:這個命令就是將操作符3也指向標准輸入。
exec 總結
exec命令 |
作用 |
exec ls |
在shell中執行ls,ls結束后不返回原來的shell中了 |
exec <file |
file中的內容作為標准輸入(替代STDIN) |
exec >file |
將標准輸出寫入file(替代STDOUT) |
exec 3<file |
將file讀入到文件描述符3中(此時,創建了文件描述符3) |
sort <&3 |
將文件描述符3作為臨時輸入,用於sort排序 |
exec 4>file |
將寫入文件描述符4中的內容寫入file中(此時,創建了文件描述符4) |
ls >&4 |
Ls將不會有顯示,直接寫入文件描述符4中了,即上面的file中 |
exec 5<&4 |
創建文件描述符4的拷貝文件描述符5 |
exec 3<&- |
關閉文件描述符3 |
exec使用示例
2.exec I/O重定向詳解及應用實例
2.1 基本概念
a、 me/O重定向通常與 FD有關,shell的FD通常為10個,即 0~9;
b、 常用FD有3個,為0(stdin,標准輸入)、1(stdout,標准輸出)、2(stderr,標准錯誤輸出),默認與keyboard、monitor、monitor有關;
c、 用 > 來改變送出的數據信道(stdout, stderr),使之輸出到指定的檔案;
e、 在IO重定向 中,stdout 與 stderr 的管道會先准備好,才會從 stdin 讀進資料;
f、 管道“|”(pipe line):上一個命令的 stdout 接到下一個命令的 stdin;
g、 exec 命令:常用來替代當前 shell 並重新啟動一個 shell,換句話說,並沒有啟動子 shell。使用這一命令時任何現有環境都將會被清除。exec 在對文件描述符進行操作的時候,也只有在這時,exec 不會覆蓋你當前的 shell 環境。
2.2、cmd &n 使用系統調用 dup (2) 復制文件描述符 n 並把結果用作標准輸出
&- 關閉標准輸出
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 時,這個就具有特殊的用途了。請大家務必理解這一點。
2.3、 如果 stdin, stdout, stderr 進行了重定向或關閉, 但沒有保存原來的 FD, 可以將其恢復到 default 狀態嗎?
*** 如果關閉了stdin,因為會導致退出,那肯定不能恢復。
*** 如果重定向或關閉 stdout和stderr其中之一,可以恢復,因為他們默認均是送往monitor(但不知會否有其他影響)。如恢復重定向或關閉的 stdout: exec 1>&2 ,恢復重定向或關閉的stderr:exec 2>&1。
*** 如果stdout和stderr全部都關閉了,又沒有保存原來的FD,可以用:exec 1>/dev/tty 恢復。
2.4、 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 0
exec 1>outfilename # 打開文件outfilename作為stdout
exec 2>errfilename # 打開文件 errfilename作為 stderr
exec 0&- # 關閉 FD1
exec 5>&- # 關閉 FD5
2.6、這個命令還可以作為find命令的一個選項
在當前目錄下(包含子目錄),查找所有txt文件並找出含有字符串”bin”的行
find ./ -name “*.txt” -exec grep “bin” {}
在當前目錄下(包含子目錄),刪除所有txt文件
find ./ -name “*.txt” -exec rm {}
資料來源: