1. 程式人生 > >shell指令碼的函式介紹和使用案例

shell指令碼的函式介紹和使用案例

#前言:今天我們來聊聊shell指令碼中的函式知識,看一下函式的優勢,執行過程和相關的使用案例,我們也來看一下shell和python的函式書寫方式有什麼不同

#簡介

1、函式也具有別名類似的功能
2、函式是把程式裡多次呼叫相同的程式碼部分定義成一份,然後給這份程式碼定義個名字,如果出現重複的就呼叫就行了

 

#函式的優勢

1、把相同的程式段定義成函式,可以減少整個程式的程式碼量
2、可以讓程式程式碼結構更清晰
3、增加程式的可讀、易讀性、以及管理性
4、可以實現程式功能模組化,不同的程式使用函式模組化

 

#語法格式

函式名(){
    指令
    return n
}

規範寫法
function 函式名(){
    指令
    return n
}
#提示:shell的返回值是exit輸出返回值,函式裡用return輸出返回值        

 

#函式的執行

呼叫函式
#1、直接執行函式名即可(不帶括號) #注意 執行函式時,函式後的小括號不要帶了 函式定義及函式整體必須在要執行的函式名的前面定義 #2、帶引數的函式執行方法 函式名 引數1 引數2 #提示:函式的傳參和指令碼的傳參類似 #shell的位置引數($1 $2 $3 $4 $5 $# $* $? $@)都可以時函式的引數 #$0比較特殊,仍然是父指令碼的名稱 #在shell函式裡面,return命令功能與shell裡的exit類似,作用時跳出函式 #在shell函式裡面使用exit會退出整個shell指令碼,而不是退出shell函式 #return語句會返回一個退出值(返回值)給呼叫函式的程式

 

#我們來看一下python的函式書寫方式

#提示:def是define的意思,定義

最基本的語法:
    def 函式名():
        函式體
   函式名() #呼叫函式

帶有引數的語法
def 函式名(形參列表):
    函式體(程式碼塊,return)
    
函式名(實參列表) :呼叫 

 

#看一下執行過程

# def wan():  #定義函式
#     print("今天一起去玩")
#     print("去哪裡玩呢")
#     print("我不知道")
# wan()  #呼叫函式
'''講解執行的過程
    1.定義函式wan()
    2.呼叫函式wan()
    3.準備開始執行函式
    4.列印,今天一起去玩
    5.列印,去哪裡完
    6.列印,我不知道
    7.函式執行完畢,本次呼叫完畢,wan()函式呼叫完畢
'''

 

#使用

#例1:沒有去呼叫函式

[root@shell scripts]# pwd
/scripts
[root@shell scripts]# cat hs01.sh 
#!/bin/bash

guoke(){
    echo "I am guoke"
}
[root@shell scripts]# sh hs01.sh  
[root@shell scripts]#  #如果沒有去呼叫函式的話,那麼就沒有輸出

 

#例2:呼叫函式

[root@shell scripts]# cat hs01.sh 
#!/bin/bash

guoke(){
    echo "I am guoke"
}
guoke  #呼叫函式
[root@shell scripts]# sh hs01.sh 
I am guoke

 

#例3:多次呼叫

[root@shell scripts]# cat hs01.sh 
#!/bin/bash

guoke(){
    echo "I am guoke"
}
guoke
guoke
guoke

[root@shell scripts]# sh hs01.sh 
I am guoke
I am guoke
I am guoke

 

#例4:將函式寫到/etc/init.d/functions裡面,然後通過其他指令碼進行呼叫

#/etc/init.d/functions
boy(){
    echo "I am guoke-boy"
}

return 0
#提示:不要放在return 0後面,要不然就是退出了,沒有呼叫

[root@shell scripts]# cat hs01.sh   #通過指令碼去呼叫boy函式
#!/bin/bash

. /etc/init.d/functions  #引入系統函式庫
guoke(){
    echo "I am guoke"
}
guoke
boy #呼叫/etc/init.d/functions中的函式
[root@shell scripts]# sh hs01.sh #執行之後列印 I am guoke I am guoke-boy

 

#例5:將函式寫到/etc/init.d/functions裡面,通過其他指令碼進行呼叫然後傳參

#/etc/init.d/functions
boy(){
    echo "I am $1"
}
#提示:$1:指令碼的傳入的第一個引數
[root@shell scripts]# cat hs01.sh   #通過指令碼去呼叫boy函式
#!/bin/bash

. /etc/init.d/functions  #引入系統函式庫
guoke(){
    echo "I am guoke"
}
guoke
boy guoke-boy #呼叫/etc/init.d/functions中的函式,後面接著傳參

[root@shell scripts]# sh hs01.sh  #執行之後列印
I am guoke
I am guoke-boy

 

 #例6:設定提示函式,如果傳的引數的值不符合就列印幫助函式

[root@shell scripts]# cat hs02.sh 
#!/bin/bash
usage(){
    echo "Usage:
$0 key beginservernum endservernum

example:
$0 ff 1 2"
}

[[ $# != 3 ]] && usage && exit 1  #如果傳入的引數不等於3的話,就呼叫後面的函式,並退出指令碼
[[ -z $1 || -z $2 || -z $3 ]] && usage && exit 1 #如果傳入的$1,$2,$3三個引數的值為空,那麼就呼叫後面的函式,並退出指令碼

[root@shell scripts]# sh hs02.sh 22 33 #當傳入的引數不等於3個的時候就執行usage函式,並退出指令碼 Usage: hs02.sh key beginservernum endservernum example: hs02.sh ff 1 2

 

#例7:將函式的傳參轉換成指令碼檔案命令列傳參,判斷任意指定的URL是否存在異常

[root@shell scripts]# cat hs03.sh 
#!/bin/bash

. /etc/init.d/functions

function usage(){
    echo $"usage:$0 url"
    exit 1
}

function check_url(){
    wget --spider -q -o /dev/null --tries=1 -T 5 $1
    if [ $? -eq 0 ];then
    action "$1 is success." /bin/true
    else
    action "$1 is failure." /bin/false
    fi
}

function main(){
    if [ $# -ne 1 ];then
    usage
    fi
    check_url $1
}
main $*

#引數解釋

. /etc/init.d/functions  #引入系統函式庫
function usage(){  #幫助函式

function check_url(){  #檢測URL函式
     wget --spider -q -o /dev/null --tries=1 -T 5 $1  #--spider:判斷網址是否有效,-q:不顯示執行過程,-o:將軟體輸出資訊儲存到軟體,-T:指定超時時間
     action "$1 is success." /bin/true  #action:呼叫系統函式庫的用法

function main(){  #主函式
    if [ $# -ne 1 ];then  #判斷:如果傳參的引數不等1個,那麼久列印幫助函式,提示使用者
    check_url $1 #接收函式的傳輸
main $* #$*:把命令列接收的所有引數作為函式引數傳給函式內部

 

#測試

[root@shell scripts]# sh hs03.sh   #如果沒有加引數,就呼叫提示函式
usage:hs03.sh url
[root@shell scripts]# sh hs03.sh  www.guokeboy.com  #輸入錯誤地址
www.guokeboy.com is failure.                               [FAILED](失敗)
[root@shell scripts]# sh hs03.sh www.baidu.com  #輸入正確地址
www.baidu.com is success.                                  [  OK  ]

 

#例8:給任意字串加指定顏色

[root@shell scripts]# cat hs04.sh 
#!/bin/bash

RED_COLOR='\E[1;31m'
GREEN_COLOR='\E[1;32m'
YELLOW_COLOR='\E[1;33m'
BLUE_COLOR='\E[1;34m'
PINK='\E[1;35m'
RES='\E[0m'

usage(){
    if [ $# -ne 2 ];then
    echo "USAGE:$0 {red|green|yellow|blue|pink}" contents
    exit 1
    fi
}

color(){
    case "$1" in
        red)
        echo -e "${RED_COLOR} $2 ${RES}"
    ;;
    green)
        echo -e "${GREEN_COLOR} $2 ${RES}"
    ;;
    yellow)
        echo -e "${YELLOW_COLOR} $2 ${RES}"
    ;;
    blue)
        echo -e "${BLUE_COLOR} $2 ${RES}"
    ;;
    *)
        usage
    esac
}

main(){
    if [ $# -ne 2 ];then
    usage
    fi
    color $1 $2
}
main $*

#引數解釋

#1.定義顏色變數
    數字對應的顏色:30(黑色)、31(紅色)、32(綠色)、33(黃色)、34(藍色、35(粉紅)、36(青色)、37(白色)
#2.定義幫助函式
#3.定義顏色函式,使用case來獲取輸入的值
#4.主函式,判斷輸入的引數是否為2個,如果不是就呼叫幫助函式 

 

#測試

#如果執行指令碼,不加引數的話就列印幫助函式

 

#例9:使用shell函式開發rsync服務啟動指令碼

#使用start、stop、restart函式將程式碼 模組化,使用系統函式action優化顯示

[root@shell init.d]# cat rsyncd 
#!/bin/bash
#chkconfig: 2345 20 80
#description: Rsyncd start scripts by guoke.

. /etc/init.d/functions

function usage(){
    echo $"usage:$0 {start|stop|restart}"
    exit 1
}

function start(){
    rsync --daemon
    sleep 1
    if [ `netstat -unplt | grep rsync | wc -l` -ge 1 ];then
      action "rsyncd is started." /bin/true
    else
      action "rsyncd is started." /bin/false
    fi
}

function stop(){
    killall rsync &>/dev/null
    sleep 2
    if [ `netstat -unptl | grep rsync |wc -l` -eq 0 ];then
      action "rsyncd is stopped." /bin/true
    else
      action "rsyncd is stopped." /bin/false
    fi
}

function restart(){
    stop
    sleep 2
    start
}

function main(){
    if [ $# -ne 1 ];then
    usage
    fi
    case "$1" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    restart)
        stop
        sleep 1
        start
    ;;
    *)
        usage

    esac
}
main $*

 #引數解釋:引入系統函式庫,定義幫助函式,然後定義start函式,stop函式,restart函式,定義主函式,主函式裡面首先使用if判斷傳入的引數是不是為一個,如果不是就呼叫幫助函式,然後使用case語句獲取傳入的引數,再呼叫相關的函式,$*:把命令列接收的所有引數作為函式引數傳給函式內部

 

 #測試

[root@shell init.d]# sh rsyncd stop
rsyncd is stopped.                                         [  OK  ]
[root@shell init.d]# sh rsyncd start
rsyncd is started.                                         [  OK  ]
[root@shell init.d]# sh rsyncd restart
rsyncd is stopped.                                         [  OK  ]
rsyncd is started.                                         [  OK  ]

 

#總結:將指令碼中功能進行模組化之後,就會使指令碼比較易讀和清晰,提升管理效率。好了,這次就分享到這了,寫的不好地方還望指出,多多交流提高,下次再會。。。