成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何復用外部Shell腳本

系統 Linux
在Linux開發中,經常會編寫shell腳本來執行一些任務,通常是一個腳本只做一件事,隨著任務的增加,腳本會越來越多,可復用的地方也會逐漸增加,這時就需要提取出腳本中的公共的功能放到一個通用的腳本中,其他腳本都能復用它。

 [[349781]]

本文轉載自微信公眾號「Linux開發那些事兒」,作者LinuxThings。轉載本文請聯系Linux開發那些事兒公眾號。  

在Linux開發中,經常會編寫shell腳本來執行一些任務,通常是一個腳本只做一件事,隨著任務的增加,腳本會越來越多,可復用的地方也會逐漸增加,這時就需要提取出腳本中的公共的功能放到一個通用的腳本中,其他腳本都能復用它

本篇文章介紹shell腳本中如何執行外部腳本,如何調用外部腳本中的函數,以及腳本復用相關的方法

執行外部腳本的方式

假如在當前目錄有 a.sh 腳本,內容如下

  1. #!/bin/bash 
  2.  
  3. echo "a.sh..." 

在一個腳本中執行外部腳本主要有以下幾種方式

  • source 外部腳本名字

在當前目錄下的 b.sh 腳本,內容如下:

  1. #!/bin/bash 
  2.  
  3. source a.sh 
  4. echo "b.sh..." 

執行 ./b.sh,結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh  
  2. a.sh... 
  3. b.sh... 

腳本中 source a.sh 命令 會先執行當前目錄下的 a.sh腳本,所以結果會先輸出 a.sh...再輸出 b.sh腳本本身的打印

  • 點號 外部腳本名字

把 b.sh 腳本中執行a.sh腳本的語句修改成 點號 + 空格 + a.sh ,修改之后的腳本內容如下:

注意:點號和a.sh之間一定要加上空格,否則執行的時候會出錯

  1. #!/bin/bash 
  2.  
  3. . a.sh 
  4. echo "b.sh..." 

執行 ./b.sh,結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh  
  2. a.sh... 
  3. b.sh... 

在上述腳本中, . a.sh 會先執行a.sh腳本, 結果會先輸出 a.sh...再輸出 b.sh...

  • sh 外部腳本名字

sh 外部腳本名字 和 ./外部腳本名字 兩種方式是一樣的,選擇哪一種方式都沒問題,下面是以前面一種方式為例說明的

把 b.sh 腳本中 source a.sh修改成 sh a.sh ,修改之后的腳本內容如下:

  1. #!/bin/bash 
  2.  
  3. sh a.sh 
  4. echo "b.sh..." 

執行 ./b.sh 命令, 結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh  
  2. a.sh... 
  3. b.sh... 

可以看出,結果輸出和上面兩種方式是一樣的

三種方式的有什么區別

調用外部腳本有 source 外部腳本 、點號 外部腳本、sh 外部腳本 三種方式,它們之間有什么區別呢?

其中,source 外部腳本 和 點號 外部腳本 兩種方式是相同的,當前腳本繼承了外部腳本的全局變量和函數, 相當于把外部腳本的函數和全局變量導入了當前腳本中

修改 a.sh 和 b.sh 腳本, 內容如下

a.sh腳本

  1. #!/bin/bash 
  2.  
  3. VAR_A=10 
  4.  
  5. func_a() 
  6.   echo "a.sh...pid:$$,param:$1" 

b.sh腳本

  1. #!/bin/bash 
  2.  
  3. source a.sh  
  4.  
  5. func_a $1 
  6. echo "vara:$VAR_A" 
  7. echo "b.sh...pid:$$" 

執行 ./b.sh 5 命令,結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh 5 
  2. a.sh...pid:21485,param:5 
  3. vara:10 
  4. b.sh...pid:21485 

兩個腳本中的 $$ 是指執行腳本的進程ID,從結果可以看出,a.sh 和 b.sh 都是在同一個進程內執行的,所以在 b.sh 腳本中執行 source a.sh 命令,會把 a.sh 腳本中的全局變量 VAR_A 和函數 func_a導入到 b.sh中

在 b.sh中打印變量 VAR_A,輸出的值和 a.sh中相同,調用 func_a函數,輸出也說明了調用的是 a.sh中的函數

source 外部腳本 、點號 外部腳本 兩種方式是相同的, 所以, 把 b.sh 中 source a.sh 修改成 . a.sh , 執行 ./b.sh 5, 結果依然是相同的

由于 sh 外部腳本的方式是當前腳本和外部腳本在兩個不同的進程中執行,所以當前腳本不能直接使用外部腳本中的函數和全局變量

修改 a.sh 和 b.sh 腳本, 內容如下

a.sh腳本

  1. #!/bin/bash 
  2.  
  3. test_a() 
  4.   echo "a.sh...test_a" 
  5.  
  6. echo "a.sh...pid:$$" 

b.sh腳本

  1. #!/bin/bash 
  2.  
  3. sh a.sh 
  4.  
  5. echo "b.sh...pid:$$" 
  6.  
  7. test_a 

執行 ./b.sh 命令,結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh  
  2. a.sh...pid:21818 
  3. b.sh...pid:21817 
  4. ./b.sh:行7: test_a: 未找到命令 

從結果可以看出,執行 a.sh 和 b.sh 的進程ID是不同的,b.sh腳本進程找不到test_a函數,所以在b.sh中調用test_a 函數會提示 未找到命令

調用外部腳本中的函數

上一節講到 sh 外部腳本 的方式無法直接使用外部腳本中函數和全局變量,下面提供幾種方法可以解決這個問題

  • case 分支選擇

這種方法類似于程序代碼中的 switch case 語句,通過switch 選擇不同的分支從而執行不同的邏輯,shell腳本中是使用case關鍵字來實現的

a.sh腳本

  1. #!/bin/bash 
  2.  
  3. VAR_A=10 
  4.  
  5. test_a() 
  6.    echo "test_a..pid:$$,p1:$1,p2:$2" 
  7. get_var() 
  8.   echo ${VAR_A} 
  9.  
  10. case "$1" in 
  11.     ta) 
  12.       test_a $2 $3 
  13.       ;; 
  14.     var) 
  15.       get_var 
  16.       ;; 
  17.    *) 
  18.       echo "parameter err..." 
  19. esac 

b.sh腳本

  1. #!/bin/bash 
  2.  
  3. echo "b.sh...pid:$$" 
  4.  
  5. sh a.sh ta 3 5 
  6.  
  7. ret=$(sh a.sh var) 
  8.  
  9. echo "ret:$ret" 

執行 ./b.sh 命令,結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh  
  2. b.sh...pid:24813 
  3. test_a..pid:24814,p1:3,p2:5 
  4. ret:10 

腳本b.sh一開始打印了調用自身的進程ID

sh a.sh ta 3 5 語句是調用a.sh腳本,傳入的三個參數分別是ta, 3, 5 ,執行a.sh時,傳入的第一個參數 ta經過case匹配之后調用 test_a函數,并把剩下的兩個參數 3和5作為參數傳入函數

ret=$(sh a.sh var) 語句時調用a.sh腳本,傳入一個var 參數,經過case匹配之后調用get_var函數,該函數的作用輸出腳本中全局變量VAR_A的值,語句中$()的作用是獲取()中命令的返回值,這里是把a.sh腳本中 get_var函數的返回值賦值給 ret變量,所以該變量的值是 a.sh腳本中全局變量VAR_A的值

說明:如果想要獲取函數的返回值,可以在函數中用 echo 打印相應的輸出值,然后使用$(函數名 參數列表)可以獲取到函數中打印的值,如上面b.sh腳本中 ret=$(sh a.sh var)語句,變量ret的值是 a.sh腳本中 get_var函數輸出的值10

這里需要注意的是, 如果函數中有echo調試日志,那么調試日志也會一起返回

  • 函數調用模板

上面介紹的用 case 關鍵字去匹配調用不同的函數有一個缺點,每次a.sh腳本中增加一個函數的時候,case 就需要添加一個分支,分支里調用不同的函數,還需要注意函數是否有參數傳入以及參數數量是否正確

我們可以在每個供外部調用腳本的尾部加上以下的語句,就可以解決上述問題, 具體語句如下

  1. if [ $# -ge 1 ]; then 
  2.    name="$1" 
  3.    shift 1 
  4.    $name "$@" 
  5. fi 

上述語句首先判斷調用腳本時傳入的參數數量,只有參數數量大于等于1才有效,傳入的第一個參數表示函數名字,從第二個參數到最后一個參數都會作為參數傳入到函數中

這里的 shift 1 是把傳入腳本的參數左移一個位置,比如:傳入腳本參數有 $1 $2 $3三個參數,左移一個位置之后, $2 移動到 $1 的位置,$3 移動到 $2 的位置,參數數量變為2了

原因: 傳入腳本的參數中,第一個參數是函數名字,從第二個參數起才是函數的參數,如果不做左移處理,第一個參數函數名字也會作為參數傳入到函數中

下面是完整的腳本內容

a.sh腳本

  1. #!/bin/bash 
  2.  
  3. VAR_A=10 
  4.  
  5. test_a() 
  6.    echo "test_a..pid:$$,p1:$1,p2:$2" 
  7.  
  8. get_var() 
  9.   echo ${VAR_A} 
  10.  
  11. if [ $# -ge 1 ]; then 
  12.    name="$1" 
  13.    shift 1 
  14.    $name "$@" 
  15. fi 

b.sh腳本

  1. #!/bin/bash 
  2.  
  3. echo "b.sh...pid:$$" 
  4.  
  5. sh a.sh test_a 3 5 
  6.  
  7. ret=$(sh a.sh get_var) 

執行 ./b.sh 命令,結果如下

  1. [root@ecs-centos-7 ~]# ./b.sh  
  2. b.sh...pid:25086 
  3. test_a..pid:25087,p1:3,p2:5 
  4. ret:10 

可以看出,結果和上面 case 的方法是一樣的

現在其他腳本中都可以通過 sh a.sh 函數名 參數列表 這樣的方式調用 a.sh 腳本中的函數了,通過 $(sh a.sh 函數名 參數列表)的方式獲取 a.sh腳本函數的返回值

  • 兩者的優缺點

與case分支選擇的方式相比,函數調用模板的優點是調用者只需要關心復用的腳本中函數名、函數傳入參數、函數返回值就可以直接使用

缺點是如果有多個腳本都調用了復用腳本中的函數,當復用腳本中函數名變更時,需要修改所有調用了它的地方

函數調用模板方式的缺點恰恰是case分支選擇方式的有點,case分支選擇的方式時根據傳入的字符串參數調用不同的函數,這里的字符串參數相當于函數的別名,只要這個參數保持不變,腳本中的函數名字可以任意變更

上述的優缺點比較只是一個相對的比較,實際應用中下不會很明顯,大部分情況兩種方式都可以使用

小結

在編寫shell腳本的過程中,經常會遇到一些莫名奇妙的問題,有些問題就算撓破頭皮都不知道如何解決,腳本復用可以把一些公共功能提取出來,形成一個個的功能模塊,不僅有助于減少我們編寫腳本時犯的錯誤,而且對后期的腳本維護很有幫助

 

責任編輯:武曉燕 來源: Linux開發那些事兒
相關推薦

2021-07-02 06:54:44

Shell腳本 Linux

2023-05-20 17:45:25

LinuxShell

2014-05-16 11:38:27

Shell 腳本監控

2019-08-09 13:50:08

shellLinux

2021-08-20 10:46:25

Shell腳本文件Linux

2021-04-21 08:03:34

腳本Shell讀取

2024-11-27 09:19:25

2017-03-27 14:16:52

Vimshell命令

2020-12-14 06:57:37

shell

2011-09-27 13:52:41

2020-06-17 10:42:54

shellshell腳本Linux

2009-11-18 13:52:30

PHP shell腳本

2023-07-31 08:45:10

Shell腳本

2018-02-01 17:32:30

LinuxUNIXBash Shell

2022-05-02 18:29:35

bashshellLinux

2017-01-18 20:38:36

LinuxShell腳本命令

2016-12-16 09:23:29

LinuxShell腳本

2016-12-20 09:30:22

shell腳本linux

2021-03-14 09:28:24

Linux Shell腳本

2022-12-22 20:47:01

腳本循環結構
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕一区二区三区在线观看 | 午夜视频在线免费观看 | 久久午夜剧场 | 自拍亚洲 | 欧美一级高潮片免费的 | 国产色视频网站 | 亚洲高清视频在线 | 97精品国产97久久久久久免费 | 亚洲视频一区二区三区 | 97精品视频在线 | 国产成人精品a视频一区www | 中文字幕电影在线观看 | 国产在线中文字幕 | 国产精品高潮呻吟久久 | 男女羞羞视频免费看 | 国产精品久久久久久久久免费丝袜 | 色眯眯视频在线观看 | 欧美色性 | 久久精品欧美视频 | 91久久精品国产91久久 | 激情91 | 91精品无人区卡一卡二卡三 | www.日韩| 国产精品免费在线 | 天堂中文资源在线 | 国产丝袜一区二区三区免费视频 | 国产网站久久 | 黄视频网址| 欧美a级成人淫片免费看 | 亚洲欧洲在线看 | 理论片87福利理论电影 | 干狠狠 | 国产免费看 | 日韩欧美一区二区三区免费观看 | 亚洲a视频| 中文字幕日韩av | 精品久久久久久亚洲综合网站 | 91视频在线 | 成人一级黄色毛片 | 青青久在线视频 | 中文字幕国产第一页 |