shell腳本exec
① 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
② 執行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。
③ 【exec】shell腳本中的 exec 命令
exec 是 bash 的內置命令
shell 的內件命令exec執行命令時,不啟用新的shell進程。
source 和 . 不啟用新的shell,在當前shell中執行,設定的局部變數在執行完命令後仍然有效。
bash 或 sh 或 shell script 執行時,另起一個子shell,其繼承父shell的環境變數,其子shelll的變數執行完後不影響父shell。
exec是用被執行的命令行替換掉當前的shell進程,且exec命令後的其他命令將不再執行。
例如在當前shell中執行 exec ls 表示執行ls這條命令來替換當前的shell ,即為執行完後會退出當前shell。
為了避免這個結果的影響,一般將exec命令放到一個shell腳本中,用主腳本調用這個腳本,調用處可以用bash xx.sh(xx.sh為存放exec命令的腳本),這樣會為xx.sh建立一個子shell去執行,當執行exec後該子腳本進程就被替換成相應的exec的命令。
其中有一個例外:當exec命令對文件描述符操作的時候,就不會替換shell,而是操作完成後還會繼續執行後面的命令!
在shell腳本中使用exec命令,根據操作的對象不同會有不同的行為
文件描述符
shell中描述符一共有12個
0 代表標准輸入
1 代表標准輸出
2 錯誤輸出
其他 3-9 都是空白描述符
# exec3>&1 4>&2 1>> bash.log 2>&1
其含義是: 復制標准輸出到3 ,錯誤輸出到 4 ,把 3 4 保存在bash.log 這個文件中。
# ./bash.sh >> bash.log 2>&1
其含義是:將bash.sh腳本執行的標准輸出和錯誤輸出追加重定向到 bash.log
如果exec 跟的是其他命令,則其他命令結束後,本shell也隨之停止
# cat test_exec.sh
###################
#!/bin/bash
#
echo "Hello mysql"
exec echo "Hello oracle"
echo "Hello sqlserver"
####################
可以看到隨著 echo " hello oracle" 這條指令運行完本 整個腳本執行完畢,後面的 echo " hello db2" 沒有執行!
Linux shell 腳本中, $@ 和$# 分別是什麼意思?
$@ 表示所有腳本參數的內容
$# 表示返回所有腳本參數的個數
示例:編寫如下shell腳本,保存為test.sh
###############
#!/bin/sh
echo "number:$#"
echo "argume:$@"
###############
執行腳本:
./test.sh first_arg second_arg
說明:給腳本提供了兩個參數,所以$#輸出的結果是2,$@代表了參數的內容!
怎麼理解shell腳本中 exec "`dirname "$0"`/node""$0" "$@" ?
$0 # 腳本自己的路徑
"`dirname "$0"`"/node # 腳本目錄下的node程序的路徑
$@ # 腳本被執行時的命令行參數
合起來就是:用腳本目錄下的node程序來解釋這個腳本本身
exec scala "$0" "$@"是什麼意思
這是bash語法。
$0 表示當前腳本的名字
$@ 表示當前腳本執行的所有參數
exec scala "$0" "$@" 表示用scala命令,帶參數,執行當前腳本
exec sh "$0 在這個文件里,exec sh $0是什麼意思?
############
#!/bin/sh
echo "Hello!"
sleep 2
execsh "$0"
#############
$0 是位置參數,表示腳本名稱
$1 表示腳本的第一個參數,依次類推直到$9
exec用於執行命令、或腳本、或外部可執行程序,會新建一個shell去執行
綜上,這里exec sh "$0" 就是執行腳本本身
所以,就是一個循環過程,每隔兩秒列印一次 Hello
#############
#!/bin/sh
echo "Hello!"
sleep 2
exec "$0"
#############
④ 關於shell腳本#!的說明
Unix環境下的shell腳本通常都是#!/bin/sh開頭,那麼這句描述符究竟是什麼含義呢,我試圖解答這個問題。
首先#!必須出現在shell腳本的開頭位置,後面跟一個shell解析器,比如/bin/sh,或者/bin/bash,或者/usr/bin/ksh, 等等.
我們看到 a.sh使用的可執行程序是/bin/bash,這個/bin/bash是在a.sh文件裡面通過#!指定的。
a.out是一個可執行程序(ELF格式),它可以獨自運行,但是不能通過一個shell來運行。
#!實際上就是文件的魔數(magic number)
我們知道ELF格式為文件頭4個字元是".ELF",即(0x 7f 45 4c 46),而其實字元"#!"是shell腳本文件的魔數,即(0x 23 21),因為shell腳本是文本文件,#!就是兩個可讀的魔數字元。
這個魔數是干什麼用的呢?它是被操作系統exec系列函數使用的,exec函數需要載入一個文件時,它會讀取文件開頭魔數域,如果是".ELF",那麼就是一個ELF格式的可執行文件,如果是"#!"那麼就是一個腳本文件,然後再從"#!"後面繼續讀取腳本解析器,最後調用腳本解析器可執行程序,並把腳本本身作為參數傳遞給他。
注意
當前shell會讀取文件file的魔數
我也不清楚為什麼sh file格式不能支持file是二進制可執行程序,理論上sh還是可以去分析file的魔數,從而判斷file的類型,然後做區分處理。
https://en.wikipedia.org/wiki/Shebang_(Unix)
