您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“怎么復(fù)用外部Shell腳本”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“怎么復(fù)用外部Shell腳本”這篇文章吧。
執(zhí)行外部腳本的方式
假如在當(dāng)前目錄有 a.sh 腳本,內(nèi)容如下
#!/bin/bash echo "a.sh..."
在一個(gè)腳本中執(zhí)行外部腳本主要有以下幾種方式
source 外部腳本名字
在當(dāng)前目錄下的 b.sh 腳本,內(nèi)容如下:
#!/bin/bash source a.sh echo "b.sh..."
執(zhí)行 ./b.sh,結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh a.sh... b.sh...
腳本中 source a.sh 命令 會(huì)先執(zhí)行當(dāng)前目錄下的 a.sh腳本,所以結(jié)果會(huì)先輸出 a.sh...再輸出 b.sh腳本本身的打印
點(diǎn)號(hào) 外部腳本名字
把 b.sh 腳本中執(zhí)行a.sh腳本的語(yǔ)句修改成 點(diǎn)號(hào) + 空格 + a.sh ,修改之后的腳本內(nèi)容如下:
注意:點(diǎn)號(hào)和a.sh之間一定要加上空格,否則執(zhí)行的時(shí)候會(huì)出錯(cuò)
#!/bin/bash . a.sh echo "b.sh..."
執(zhí)行 ./b.sh,結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh a.sh... b.sh...
在上述腳本中, . a.sh 會(huì)先執(zhí)行a.sh腳本, 結(jié)果會(huì)先輸出 a.sh...再輸出 b.sh...
sh 外部腳本名字
sh 外部腳本名字 和 ./外部腳本名字 兩種方式是一樣的,選擇哪一種方式都沒(méi)問(wèn)題,下面是以前面一種方式為例說(shuō)明的
把 b.sh 腳本中 source a.sh修改成 sh a.sh ,修改之后的腳本內(nèi)容如下:
#!/bin/bash sh a.sh echo "b.sh..."
執(zhí)行 ./b.sh 命令, 結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh a.sh... b.sh...
可以看出,結(jié)果輸出和上面兩種方式是一樣的
三種方式的有什么區(qū)別
調(diào)用外部腳本有 source 外部腳本 、點(diǎn)號(hào) 外部腳本、sh 外部腳本 三種方式,它們之間有什么區(qū)別呢?
其中,source 外部腳本 和 點(diǎn)號(hào) 外部腳本 兩種方式是相同的,當(dāng)前腳本繼承了外部腳本的全局變量和函數(shù), 相當(dāng)于把外部腳本的函數(shù)和全局變量導(dǎo)入了當(dāng)前腳本中
修改 a.sh 和 b.sh 腳本, 內(nèi)容如下
a.sh腳本
#!/bin/bash VAR_A=10 func_a() { echo "a.sh...pid:$$,param:$1" }
b.sh腳本
#!/bin/bash source a.sh func_a $1 echo "vara:$VAR_A" echo "b.sh...pid:$$"
執(zhí)行 ./b.sh 5 命令,結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh 5 a.sh...pid:21485,param:5 vara:10 b.sh...pid:21485
兩個(gè)腳本中的 $$ 是指執(zhí)行腳本的進(jìn)程ID,從結(jié)果可以看出,a.sh 和 b.sh 都是在同一個(gè)進(jìn)程內(nèi)執(zhí)行的,所以在 b.sh 腳本中執(zhí)行 source a.sh 命令,會(huì)把 a.sh 腳本中的全局變量 VAR_A 和函數(shù) func_a導(dǎo)入到 b.sh中
在 b.sh中打印變量 VAR_A,輸出的值和 a.sh中相同,調(diào)用 func_a函數(shù),輸出也說(shuō)明了調(diào)用的是 a.sh中的函數(shù)
source 外部腳本 、點(diǎn)號(hào) 外部腳本 兩種方式是相同的, 所以, 把 b.sh 中 source a.sh 修改成 . a.sh , 執(zhí)行 ./b.sh 5, 結(jié)果依然是相同的
由于 sh 外部腳本的方式是當(dāng)前腳本和外部腳本在兩個(gè)不同的進(jìn)程中執(zhí)行,所以當(dāng)前腳本不能直接使用外部腳本中的函數(shù)和全局變量
修改 a.sh 和 b.sh 腳本, 內(nèi)容如下
a.sh腳本
#!/bin/bash test_a() { echo "a.sh...test_a" } echo "a.sh...pid:$$"
b.sh腳本
#!/bin/bash sh a.sh echo "b.sh...pid:$$" test_a
執(zhí)行 ./b.sh 命令,結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh a.sh...pid:21818 b.sh...pid:21817 ./b.sh:行7: test_a: 未找到命令
從結(jié)果可以看出,執(zhí)行 a.sh 和 b.sh 的進(jìn)程ID是不同的,b.sh腳本進(jìn)程找不到test_a函數(shù),所以在b.sh中調(diào)用test_a 函數(shù)會(huì)提示 未找到命令
調(diào)用外部腳本中的函數(shù)
上一節(jié)講到 sh 外部腳本 的方式無(wú)法直接使用外部腳本中函數(shù)和全局變量,下面提供幾種方法可以解決這個(gè)問(wèn)題
case 分支選擇
這種方法類(lèi)似于程序代碼中的 switch case 語(yǔ)句,通過(guò)switch 選擇不同的分支從而執(zhí)行不同的邏輯,shell腳本中是使用case關(guān)鍵字來(lái)實(shí)現(xiàn)的
a.sh腳本
#!/bin/bash VAR_A=10 test_a() { echo "test_a..pid:$$,p1:$1,p2:$2" } get_var() { echo ${VAR_A} } case "$1" in ta) test_a $2 $3 ;; var) get_var ;; *) echo "parameter err..." esac
b.sh腳本
#!/bin/bash echo "b.sh...pid:$$" sh a.sh ta 3 5 ret=$(sh a.sh var) echo "ret:$ret"
執(zhí)行 ./b.sh 命令,結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh b.sh...pid:24813 test_a..pid:24814,p1:3,p2:5 ret:10
腳本b.sh一開(kāi)始打印了調(diào)用自身的進(jìn)程ID
sh a.sh ta 3 5 語(yǔ)句是調(diào)用a.sh腳本,傳入的三個(gè)參數(shù)分別是ta, 3, 5 ,執(zhí)行a.sh時(shí),傳入的第一個(gè)參數(shù) ta經(jīng)過(guò)case匹配之后調(diào)用 test_a函數(shù),并把剩下的兩個(gè)參數(shù) 3和5作為參數(shù)傳入函數(shù)
ret=$(sh a.sh var) 語(yǔ)句時(shí)調(diào)用a.sh腳本,傳入一個(gè)var 參數(shù),經(jīng)過(guò)case匹配之后調(diào)用get_var函數(shù),該函數(shù)的作用輸出腳本中全局變量VAR_A的值,語(yǔ)句中$()的作用是獲取()中命令的返回值,這里是把a(bǔ).sh腳本中 get_var函數(shù)的返回值賦值給 ret變量,所以該變量的值是 a.sh腳本中全局變量VAR_A的值
說(shuō)明:如果想要獲取函數(shù)的返回值,可以在函數(shù)中用 echo 打印相應(yīng)的輸出值,然后使用$(函數(shù)名 參數(shù)列表)可以獲取到函數(shù)中打印的值,如上面b.sh腳本中 ret=$(sh a.sh var)語(yǔ)句,變量ret的值是 a.sh腳本中 get_var函數(shù)輸出的值10
這里需要注意的是, 如果函數(shù)中有echo調(diào)試日志,那么調(diào)試日志也會(huì)一起返回
函數(shù)調(diào)用模板
上面介紹的用 case 關(guān)鍵字去匹配調(diào)用不同的函數(shù)有一個(gè)缺點(diǎn),每次a.sh腳本中增加一個(gè)函數(shù)的時(shí)候,case 就需要添加一個(gè)分支,分支里調(diào)用不同的函數(shù),還需要注意函數(shù)是否有參數(shù)傳入以及參數(shù)數(shù)量是否正確
我們可以在每個(gè)供外部調(diào)用腳本的尾部加上以下的語(yǔ)句,就可以解決上述問(wèn)題, 具體語(yǔ)句如下
if [ $# -ge 1 ]; then name="$1" shift 1 $name "$@" fi
上述語(yǔ)句首先判斷調(diào)用腳本時(shí)傳入的參數(shù)數(shù)量,只有參數(shù)數(shù)量大于等于1才有效,傳入的第一個(gè)參數(shù)表示函數(shù)名字,從第二個(gè)參數(shù)到最后一個(gè)參數(shù)都會(huì)作為參數(shù)傳入到函數(shù)中
這里的 shift 1 是把傳入腳本的參數(shù)左移一個(gè)位置,比如:傳入腳本參數(shù)有 $1 $2 $3三個(gè)參數(shù),左移一個(gè)位置之后, $2 移動(dòng)到 $1 的位置,$3 移動(dòng)到 $2 的位置,參數(shù)數(shù)量變?yōu)?了
原因: 傳入腳本的參數(shù)中,第一個(gè)參數(shù)是函數(shù)名字,從第二個(gè)參數(shù)起才是函數(shù)的參數(shù),如果不做左移處理,第一個(gè)參數(shù)函數(shù)名字也會(huì)作為參數(shù)傳入到函數(shù)中
下面是完整的腳本內(nèi)容
a.sh腳本
#!/bin/bash VAR_A=10 test_a() { echo "test_a..pid:$$,p1:$1,p2:$2" } get_var() { echo ${VAR_A} } if [ $# -ge 1 ]; then name="$1" shift 1 $name "$@" fi
b.sh腳本
#!/bin/bash echo "b.sh...pid:$$" sh a.sh test_a 3 5 ret=$(sh a.sh get_var)
執(zhí)行 ./b.sh 命令,結(jié)果如下
[root@ecs-centos-7 ~]# ./b.sh b.sh...pid:25086 test_a..pid:25087,p1:3,p2:5 ret:10
可以看出,結(jié)果和上面 case 的方法是一樣的
現(xiàn)在其他腳本中都可以通過(guò) sh a.sh 函數(shù)名 參數(shù)列表 這樣的方式調(diào)用 a.sh 腳本中的函數(shù)了,通過(guò) $(sh a.sh 函數(shù)名 參數(shù)列表)的方式獲取 a.sh腳本函數(shù)的返回值
兩者的優(yōu)缺點(diǎn)
與case分支選擇的方式相比,函數(shù)調(diào)用模板的優(yōu)點(diǎn)是調(diào)用者只需要關(guān)心復(fù)用的腳本中函數(shù)名、函數(shù)傳入?yún)?shù)、函數(shù)返回值就可以直接使用
缺點(diǎn)是如果有多個(gè)腳本都調(diào)用了復(fù)用腳本中的函數(shù),當(dāng)復(fù)用腳本中函數(shù)名變更時(shí),需要修改所有調(diào)用了它的地方
函數(shù)調(diào)用模板方式的缺點(diǎn)恰恰是case分支選擇方式的有點(diǎn),case分支選擇的方式時(shí)根據(jù)傳入的字符串參數(shù)調(diào)用不同的函數(shù),這里的字符串參數(shù)相當(dāng)于函數(shù)的別名,只要這個(gè)參數(shù)保持不變,腳本中的函數(shù)名字可以任意變更
上述的優(yōu)缺點(diǎn)比較只是一個(gè)相對(duì)的比較,實(shí)際應(yīng)用中下不會(huì)很明顯,大部分情況兩種方式都可以使用
以上是“怎么復(fù)用外部Shell腳本”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。