1. 程式人生 > >shell腳本進階

shell腳本進階

shell腳本進階

一、流程控制

流程控制語句,即用來實現對程序流程的選擇、循環和返回等進行控制的語句。

1.條件判斷

1if條件判斷

  • 普通if條件判斷

格式:

技術分享

  • 嵌套if條件判斷

格式:

技術分享

(2)case判斷

簡潔版多分支if語句,當if語句有多個elif時可以使用case語句代替,語言更簡潔容易理解。使用場景:判斷某個變量值是否為多種情形中的一種時使用。

格式:

技術分享

示例:

技術分享

執行結果:

技術分享

2、循環

循環執行就是將循環體內的代碼重復運行多次;運行的次數由進入循環的條件和退出循環決定。

(1)for循環

格式:

技術分享

列表:變量的取值範圍,可以是變量的取值範圍,也可以是某個變量的執行結果。

執行機制:

依次將列表中的元素賦值“變量名”,每次賦值即執行一次循環體,直到列表中的元素耗盡,循環結束。

註:for循環的特殊格式:for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))

控制變量初始化:僅在運行到循環代碼段時執行一次

控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而後再做條件判斷

(2)while循環

格式:

技術分享

執行機制:

CONDITION:循環控制條件;進入循環之前,先做一次判斷;每一次循環之後會再次做判斷;條件為“true”,則執行一次循環;直到條件測試狀態為“false”終止循環

因此:CONDTION一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正

進入條件:CONDITION為true

退出條件:CONDITION為false

註:while的特殊用法:(遍歷文件的每一行)

格式:

技術分享

在執行循環的時候依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line

(3)until循環

格式:

技術分享

進入條件:CONDITION false

退出條件:CONDITION true

(4)循環控制語句continue, break 以及shift

  • 用於循環體內

  • continue 用於結束本輪循環,而進入下一輪循環

Break 用於結束整個循環 ,不會進入下一輪循環

  • shift用於將參數列表list左移指定次數,默認為一次,在處理參數不確定的情況下比較好用。

練習:

1)打印九九乘法表技術分享

shell腳本

技術分享

2)打印等腰三角形

技術分享

Shell腳本:

技術分享

3、select循環與菜單

  • select 循環主要用於創建菜單,按獅子書序排列的菜單項將顯示在標準錯誤上,並顯示PS3提符,等待用戶輸入。

  • 用戶輸入菜單列表中的某個數字,執行相應的命令

  • 用戶輸入被保存在內置變量REPLY

  • Select是個無限循環,因此要用break命令退出循環,或者用exit命令終止腳本,也可以適應ctrl +c退出循環

  • 經常和case聯合使用

示例:

技術分享

二、trap信號捕捉

  • trap ‘觸發指令信號

自定義進程收到系統發出的指定信號後,將執行觸發指令,而不會執行原操作

  • trap ‘‘ 信號

忽略信號的操作

  • trap ‘-‘ 信號

恢復原信號的操作

  • trap -p

列出自定義信號操作

示例:

技術分享三、函數

把一段具有獨立功能代碼封裝在一起,並給予命名,後續用到的時候,可以直接通過給定函數名來調用整體函數,使用函數可以實現代碼的重用和模式化編程。函數在形式上和shell程序在形式上是相似的,不同的是他不是一個單獨的進程,不能單獨運行,而是shell程序的一部分。

函數和shell程序比較相似,區別在於:

  • Shell程序是在子shell中運行

  • Shell函數是在當前shell中運行,因此在當前shell中,函數可以更改shell中的變量

1、定義函數

函數有兩部分組成:函數名和函數體

語法一:

技術分享

語法二:

技術分享

語法三:(最簡便也是最常見的)

技術分享

2、函數使用

  • 可在交互式環境下定義函數,即直接在bash命令行裏寫函數和調用函數

  • 可將函數放在腳本文件中作為它的一部分,即可以再同一個腳本文件裏調用函數

  • 可放在只包含函數的單獨文件中,即在其他shell腳本中可以調用這個文件。使用 . /path/to/functions_files 或者source /path/to/functions_files

    函數調用很簡單:

  • 無參數:function_name

  • 有參數: funcation_name ar1 arg2 ……argN 在函數體,可以使用$1,$2,…調用這些參數,還可以使用$*,[email protected]等特殊變量

  • 函數的生命周期:被調用時創建,返回時終止

declare -f :查看系統裏的函數

技術分享

3、函數返回值

  • 函數有兩種返回值:

(1)使用echo等命令進行輸出

(2) 函數體中調用命令的輸出結果

  • 函數的退出狀態碼:

(1) 默認取決於函數中執行的最後一條命令的退出狀態碼

(2) 自定義退出狀態碼,其格式為:

return 從函數中返回,用最後狀態命令決定返回值

return0 無錯誤返回。

return 1-255 有錯誤返回

4、函數變量

變量的作用域不同

  • 環境變量:當前shell和子shell有效

  • 本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量作用範圍是當前shell腳本程序文件,包括腳本中的函數

  • 局部變量:函數的生命周期;函數結束時變量被自動銷毀

由於函數是在當前shell中執行,當函數體中有變量的時候,容易與函數體外的變量產生沖突,這時候可以使用局部變量。

在函數中定義局部變量的方法

local NAME=VALUE

5、函數遞歸

函數直接或間接調用自身

階乘示例:

技術分享

6、環境函數

使函數子進程也可使用

聲明:export –f function_name

查看:export -f 或者declare -xf

函數練習示例:

編寫服務腳本/root/bin/testsrv.sh,完成如下要求

(1) 腳本可接受參數:start,stop, restart, status

(2) 如果參數非此四者之一,提示使用格式後報錯退出

(3) 如是start:則創建/var/lock/subsys/SCRIPT_NAME,並顯示啟動成功

考慮:如果事先已經啟動過一次,該如何處理?

(4) 如是stop:則刪除/var/lock/subsys/SCRIPT_NAME,並顯示停止完成

考慮:如果事先已然停止過了,該如何處理?

(5) 如是restart,則先stop, start

考慮:如果本來沒有start,如何處理?

(6) 如是status, 則如果/var/lock/subsys/SCRIPT_NAME文件存在,則顯示SCRIPT_NAMEisrunning...”

如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示SCRIPT_NAMEis stopped...”

其中:SCRIPT_NAME為當前腳本名

#!/bin/bash
. /etc/init.d/functions                                                                                                                        
var=‘/var/lock/subsys/script_service‘                                                                                                
start()
{                                                                                                                                                         
       if [ -e $var ] ;then                                                                                                                        
                echo "This service isalready running "                                                                              
       else                                                                                                                                             
                touch $var                                                                                                                         
                action " service startsucessfully "                                
       fi
}
stop ()
{
       if [ -e $var  ] ;then
                rm -f $var
                action "service stop"
       else
                action "service is notrunning" false
#               echo "service is notrunning "
       fi
}
restart ()
{
       if [ -e $var ]; then
                sleep 0.5    #間隔時間
                stop
                sleep 0.5
                  start
         else
                  action "service notrunning" /bin/false
                  sleep 0.5
                  start
          fi
  }
 status()
  {
          if [ -e $var ];then
                    echo -e "\tThe service isrunning..."
          else
                   echo -e "\tThe service isnot running..."
          fi
   }
  status()
  {  
          if [ -e $var ];then
                   echo -e "\t The serviceis running"
          else
                   echo -e "\t The serviceis stopd"
         fi
   }
  case $1 in
          start)
                   start
                  ;;
          stop)
                   stop
                   ;;
          restart)
                   restart
                   ;;
          status)
                  status
                   ;;
          *)
                   echo "Please enter thecorrect parameters (start|stop|restart|status)"
  esac






shell腳本進階