<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Linux下如何復(fù)用外部shell腳本

          共 4598字,需瀏覽 10分鐘

           ·

          2020-11-18 01:16

          在Linux開(kāi)發(fā)中,經(jīng)常會(huì)編寫(xiě)shell腳本來(lái)執(zhí)行一些任務(wù),通常是一個(gè)腳本只做一件事,隨著任務(wù)的增加,腳本會(huì)越來(lái)越多,可復(fù)用的地方也會(huì)逐漸增加,這時(shí)就需要提取出腳本中的公共的功能放到一個(gè)通用的腳本中,其他腳本都能復(fù)用它

          本篇文章介紹shell腳本中如何執(zhí)行外部腳本,如何調(diào)用外部腳本中的函數(shù),以及腳本復(fù)用相關(guān)的方法

          執(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ù)?35作為參數(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.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ì)很明顯,大部分情況兩種方式都可以使用

          小結(jié)

          在編寫(xiě)shell腳本的過(guò)程中,經(jīng)常會(huì)遇到一些莫名奇妙的問(wèn)題,有些問(wèn)題就算撓破頭皮都不知道如何解決,腳本復(fù)用可以把一些公共功能提取出來(lái),形成一個(gè)個(gè)的功能模塊,不僅有助于減少我們編寫(xiě)腳本時(shí)犯的錯(cuò)誤,而且對(duì)后期的腳本維護(hù)很有幫助


          良許個(gè)人微信


          添加良許個(gè)人微信即送3套程序員必讀資料


          → 精選技術(shù)資料共享

          → 高手如云交流社群





          本公眾號(hào)全部博文已整理成一個(gè)目錄,請(qǐng)?jiān)诠娞?hào)里回復(fù)「m」獲取!

          推薦閱讀:

          嗨:VSCode和IDEA都請(qǐng)安裝上這個(gè)神奇的插件

          雷軍1994年寫(xiě)的詩(shī)一樣的代碼,我把它運(yùn)行起來(lái)了!

          Linux 網(wǎng)絡(luò)狀態(tài)工具 ss 命令使用詳解


          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹(shù)莓派,等等。在公眾號(hào)內(nèi)回復(fù)「1024」,即可免費(fèi)獲取!!


          瀏覽 56
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青操逼| 黄色一级片免费看 | 在线亚洲免费观看 | 大香蕉伊人综合网 | 欧美性猛交ⅩXXX富婆 |