腳本exec
Ⅰ exec、source以及bash的區別
在bash shell中,source、exec以及sh都可以用來執行shell script,但是它們的差別在哪裡呢?sh:父進程會fork一個子進程,shell script在子進程中執行source:在原進程中執行,不會fork子進程exec:在原進程中執行,但是同時會終止原進程 註:使用export會把父進程中的變數向子進程中繼承,但是反過來卻不行,在子進程中,不管環境如果改變,均不會影響父進程
下面用一個例子來講解
[plain] view plain
1.sh
A=B
echo "PID for 1.sh before exec/source/fork:$"
export A
echo "1.sh: $A is $A"
case $1 in
exec)
echo "using exec..."
exec ./2.sh ;;
source)
echo "using source..."
. ./2.sh ;;
*)
echo "using fork by default..."
./2.sh ;;
esac
echo "PID for 1.sh after exec/source/fork:$"
echo "1.sh: $A is $A"
[plain] view plain
2.sh
CODE:
echo "PID for 2.sh: $"
echo "2.sh get $A=$A from 1.sh"
A=C
export A
echo "2.sh: $A is $A"
下面在命令行中去執行
./1.sh fork
可以看到,1.sh是在父進程中執行,2.sh是在子進程中執行的,父進程的PID是5344,而子進程的是5345,當子進程執行完畢後,控制權返回到父進程。同時,在子進程改變環境變數A的值不會影響到父進程。
./1.sh source
由結果可知,1.sh和2.sh都是在同一進程中執行的,PID為5367
./1.sh exec
可知,兩個腳本都是在同一進程中執行,但是請注意,使用exec終止了原來的父進程,因此,可以看到
[plain] view plain
echo "PID for 1.sh after exec/source/fork:$"
echo "1.sh: $A is $A"
這兩個命令沒有執行
由這個例子,便大致可了解它們的區別了
Ⅱ 執行shell腳本三種方法的區別:(sh、exec、source)
使用$ sh script.sh執行腳本時,當前shell是父進程,生成一個子shell進程,在子shell中執行腳本。腳本執行完畢,退出子shell,回到當前shell。
./script.sh與 sh script.sh等效。
使用$ source script.sh方式,在當前上下文中執行腳本,不會生成新的進程。腳本執行完畢,回到當前shell。
source方式也叫點命令。
. script.sh與 source script.sh等效。
使用exec command方式,會用command進程替換當前shell進程,並且保持PID不變。執行完畢,直接退出,不回到之前的shell環境。
二、測試驗證
vi loop.sh
顯示當前進程
sh的方式:執行loop.sh列印執行進程
source方式:執行loop.sh列印執行進程
exec方式:執行loop.sh列印執行進程
按下ctrl+C
sh方式:父進程是6770,執行loop.sh時的子進程是13736。執行完畢後回到父進程shell。
source方式:父進程和子進程都是6770(執行時沒有新的進程),執行完畢會回到父進程shell。
exec方式:進程PID沒有改變都是6770,執行完畢(ctrl+C強制關閉)時直接退出了shell。腳本執行時替換了父進程的shell,執行完畢後直接退出,沒有回到之前的shell。
Ⅲ shell腳本中的 exec 命令
exec執行命令時,不會啟用新的shell進程。
source和 .也不會啟用新的shell進程,在當前shell中執行,設定的局部變數在執行完命令後仍然有效。
bash或sh執行時,會另起一個子shell進程,其繼承父shell進程的環境變數,其子shell進程的變數執行完後不影響父shell進程。
exec是用被執行的命令行替換掉當前的shell進程,且exec命令後的其他命令將不再執行。
例如在當前shell中執行 exec ls 表示執行ls這條命令來替換當前的shell ,即為執行完後會退出當前shell。
為了避免父shell被退出,一般將exec命令放到一個子shell腳本中,在父sehll中調用這個子shell腳本,調用處可以用bash xx.sh(xx.sh為存放exec命令的腳本),這樣會為xx.sh建立一個子shell去執行,當執行exec後該子shell進程就被替換成相應的exec的命令。
其中有一個例外:當exec命令對文件描述符操作的時候,就不會替換shell,而是操作完成後還會繼續執行後面的命令!
文件描述符
shell中描述符一共有12個
0 代表標准輸入
1 代表標准輸出
2 錯誤輸出
其他 3-9 都是空白描述符
其含義是: 復制標准輸出到3 ,錯誤輸出到 4 ,把 3 4 保存在bash.log 這個文件中。
其含義是:將bash.sh腳本執行的標准輸出和錯誤輸出追加重定向到 bash.log
如果exec 跟的是其他命令,則其他命令結束後,本shell也隨之停止
可以看到隨著 echo " hello oracle" 這條指令運行完本 整個腳本執行完畢,後面的 echo " hello db2" 沒有執行!
二、Linux shell 腳本中, $@ 和 $@ 分別是什麼意思?
$@ 表示所有腳本參數的內容
$# 表示返回所有腳本參數的個數
示例:編寫如下shell腳本,保存為test.sh
說明:給腳本提供了兩個參數,所以 @代表了參數的內容!
怎麼理解shell腳本中 exec "`dirname "$0"`/node""$0" "$@" ?
$0 #腳本自己的路徑
"`dirname "$0"`"/node #腳本目錄下的node程序的路徑
$@ #腳本被執行時的命令行參數
合起來就是:用腳本目錄下的node程序來解釋這個腳本本身
exec scala "$0" "$@" 是什麼意思
這是bash語法。
$0 #表示當前腳本的名字
$@ #表示當前腳本執行的所有參數
exec scala "$0" "$@" #表示用scala命令,帶參數,執行當前腳本
$0 是位置參數,表示腳本名稱
$1 表示腳本的第一個參數,依次類推直到 $9
exec用於執行命令、或腳本、或外部可執行程序,會新建一個shell去執行
綜上,這里exec sh "$0" 就是執行腳本本身
所以,就是一個循環過程,每隔兩秒列印一次 Hello