Shell高級用法-----函數(function)

函數介紹(function用法)

1、function用法

1、函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程。

2、它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運 行,而是shell程序的一部分,定義函數只對當前的會話窗口有效,如果再打開一個窗口再定義另外一個函數,就對另一個窗口有效,兩者互不影響。

3、函數和shell程序比較相似,區別在於以下兩種:

(1)Shell程序在子Shell中運行。

(2)而Shell函數在當前Shell中運行。因此在當前Shell中,函數可以對shell中變量進行修改。

2、定義函數

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

help function 
語法一:  f_name (){   
  ...函數體...  
} 
語法二:  function f_name { 
   ...函數體...  
}  
語法三:  function f_name () {   
   ...函數體...  
}

可以使用declare -F 選項進行查看所有定義的函數,用unset 加上變量名 就可以刪除定義的變量

3、函數的定義和使用:

1、函數的定義和使用:

(1)可在交互式環境下定義函數

(2)可將函數放在腳本文件中作爲它的一部分

(3)可放在只包含函數的單獨文件中

2、調用:函數只有被調用纔會執行

調用:給定函數名

函數名出現的地方,會被自動替換爲函數代碼

3、函數的生命週期:被調用時創建,返回時終止

4、函數返回值

函數有兩種返回值:

1、函數的執行結果返回值:

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

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

 

 

2、函數的退出狀態碼:

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

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

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

  (1)return 0 無錯誤返回。

  (2)return 1-255 有錯誤返回

5、使用函數文件

1、可以將經常使用的函數存入函數文件,然後將函數文件載入shell

2、文件名可任意選取,但最好與相關任務有某種聯繫。例如:functions.main

3、一旦函數文件載入shell,就可以在命令行或腳本中調用函數。可以使用set命 令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數

4、若要改動函數,首先用unset命令從shell中刪除函數。改動完畢後,再重新載 入此文件

6、刪除shell函數

1、現在對函數做一些改動後,需要先刪除函數,使其對shell不可用。使用unset命 令完成刪除函數

2、命令格式爲: unset function_name 

示例: unset findit

            再鍵入set命令,函數將不再顯示

3、環境函數

(1)使子進程也可使用

(2)聲明:export -f function_name

(3)查看:export -f 或 declare -xf

7、函數參數

函數可以接受參數: 傳遞參數給函數:調用函數時,在函數名後面以空白分隔給定參數列表即可;

例如“testfunc arg1 arg2 ...”

在函數體中當中,可使用$1, $2, ...調用這些參數;還可以使用$@, $*, $# 等特殊變量

8、函數變量

變量作用域:

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

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

局部變量:函數的生命週期;函數結束時變量被自動銷燬

注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量

          在函數中定義局部變量的方法:local NAME=VALUE

 

實例1:

第一種寫法:如果命令過多,這行執行不太方便

#!/bin/bash
func_os_version () {  # 定義一個function函數名爲func_os_version,然後在大括號裏邊定義命令,取出操作系統的版本號,類似於定義別名一樣
sed -nr 's/.* ([0-9]+)\..*/\1/p' /etc/redhat-release    
}
echo OS version is `func_os_version`  # 直接寫上定義函數名稱,或者用echo 加上反向單引號進行輸出結果

查看輸出結果:

[root@centos-7 ~]# bash osversion.sh 
OS version is 7

第二種寫法:將定義的函數存放到文件中,並將要執行的腳本與定義的函數以及定義函數的文件名進行關聯

[root@centos-7 ~]# cat functions   # 將定義的函數放到functions文件中
func_os_version () {
sed -nr 's/.* ([0-9]+)\..*/\1/p' /etc/redhat-release
}
[root@centos-7 ~]# cat osversion.sh  # 將要執行腳本的函數名和上面定義函數名的文件進行關聯
#!/bin/bash
source functions  # source functions是關聯上面的文件
func_os_version  # 關聯functions裏邊定義的函數名
[root@centos-7 ~]# chmod +x osversion.sh   # 對腳本加上執行權限
[root@centos-7 ~]# ./osversion.sh   # 查看此時的執行結果即可
7

實例2:

第一步:先定義functions函數文件

[root@centos-7 data]# cat  functions  # 定義functions函數文件
func_is_digit(){
    if [ ! "$1" ];then  # 如果輸入的信息不是空,就爲真,但又不是數字
        echo "Usage:func_is_digit number"  # 請輸入數字
        return  10 
    elif [[ $1 =~ ^[[:digit:]]+$ ]];then  # 如果輸入是數字
        return 0  # return  0 返回的是正確結果,但是不會推出腳本
    else
        echo "Not a  digit"  # 如果上面都不是,就提醒不是數字
        return 1
    fi
}

第二步:調用functions函數文件,並對不同的成績分段進行判斷

[root@centos-7 data]# cat score.sh 
#!/bin/bash
source /data/functions  # 調用指定的函數文件的絕對路徑
read -p "Input your score:" SCORE
func_is_digit $SCORE  # 直接調用上面的functions文件
if [ $? -ne 0 ];then   #判斷上面的命令執行不等於0(不成功)就退出
    exit
else 
    if [ $SCORE -lt 60 ];then  # 如果成功了,對成績的三種判斷如下。
        echo "You are loser"
    elif [ $SCORE -lt 80 ];then
        echo "soso"
    else 
        echo "very good"
    fi
fi

實例3

生產中function配合case語法:

#!/bin/bash
#Author:  liupengju
#date:    2020-06-22
#TEL:     xxxxxxxxxx
#代碼發佈與回滾
set -e
set -u

#adx代碼部署變量定義
ADX_DIR=/gnome/adx
adx_new_version="gnome-adx-0.0.1-SNAPSHOT-jar-with-dependencies.jar"
ADX_NEW_MD5=`md5sum $adx_new_version | awk '{ print $1 }'`

#此行需要修改爲cf平臺的md5碼
ADX_CHK_MD5="43bcfe7594f083a8653126e0896b93ac" 

#directAd代碼部署變量定義
direct_DIR=/gnome/directAd/
direct_version="direct-ad-0.0.1-SNAPSHOT-jar-with-dependencies.jar"
direct_MD5=`md5sum $direct_version | awk '{ print $1 }'`
#direct_old_version=$(ls -l  |tail -n1 | awk '{print $9}')

#此行需要修改爲cf平臺的md5碼
direct_CHK_MD5="03c3c2fc62b2edfc92e548351010ee9f"

##########部署directAd代碼#############################
fun_copy_direct_code(){
	mv $direct_DIR/$direct_version  $direct_DIR/bak/${direct_version}_$(date +"%F-%T") 
        echo "-----上一個版本已經移動到備份目錄"
	cp /data/$direct_version  $direct_DIR  && echo "-----代碼複製成功!!!"
}

fun_chk_direct_code(){
      if [[ "$direct_MD5" == "$direct_CHK_MD5" ]];then
           echo "-----代碼校驗成功" && echo "代碼部署成功後MD5值爲:$direct_MD5"
      else
           echo "-----代碼校驗失敗" && exit
      fi
}

fun_deploy_direct_restart(){
	#$direct_DIR/restart.sh
	systemctl restart httpd
	systemctl restart nginx
	echo "後端服務重啓成功!!!"
}

fun_chk_direct_port1(){ 
#驗證端口存活狀態
	PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'`
	PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'`
     for port in $PORT1 $PORT2;do
        echo "The port is:$port------監聽端口正常"
     done
}

#############回滾direct代碼###################################
fun_rollback_direct_code(){
	cd $direct_DIR/bak
	direct_old_version=$(ls -l  |tail -n1 | awk '{print $9}')  # 提取上一個版本的jar包
	mv $direct_DIR/${direct_version} $direct_DIR/bak/${direct_version}_$(date +"%F-%T")
	mv $direct_DIR/bak/${direct_old_version} $direct_DIR/${direct_version}
	echo "------舊版本代碼移動成功"
	direct_old_MD5=$(md5sum $direct_DIR/${direct_version} |  awk '{print $1}')
	echo "代碼回滾後MD5值爲:$direct_old_MD5"
}

fun_rollback_direct_restart(){
	#$direct_DIR/restart.sh
	systemctl restart httpd
	systemctl restart nginx
	echo "--------後端服務重啓成功"
}

fun_chk_direct_port2(){
#驗證端口存活狀態
	PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'`
	PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'`
    for port in $PORT1 $PORT2;do
        echo "The port is:$port------端口監聽正常"
    done
}


#####################adx代碼部署########################################
fun_copy_adx__code(){
	mv $ADX_DIR/$adx_new_version  $ADX_DIR/bak/${adx_new_version}_$(date +"%F-%T") 
        echo "-----上一個版本已經移動到備份目錄"
	cp /data/$adx_new_version  $ADX_DIR  && echo "-----代碼複製成功!!!"
}

fun_chk_adx_code(){
	if [[ "$ADX_NEW_MD5" == "$ADX_CHK_MD5" ]];then
		echo "-----代碼校驗成功" && echo "代碼部署成功後MD5值爲:$ADX_NEW_MD5"
	else
        	echo "-----代碼校驗失敗" && exit
	fi 
}

fun_deploy_adx_restart(){
#$ADX_DIR/restart.sh
	systemctl restart httpd
	systemctl restart nginx
	echo "後端服務已經啓動!!!"
}

#驗證端口存活狀態
fun_chk_adx_port1(){
	PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'`
	PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'`
      for port in $PORT1 $PORT2;do
    	  echo "The port is:$port------監聽的端口正常啓動"
      done
}


###################################adx代碼回滾###########################
fun_rollback_adx_code(){
	cd $ADX_DIR/bak
	adx_old_version=$(ls -l  |tail -n1 | awk '{print $9}')
	mv $ADX_DIR/${adx_new_version} $ADX_DIR/bak/${adx_new_version}_$(date +"%F-%T")
	mv $ADX_DIR/bak/${adx_old_version} $ADX_DIR/${adx_new_version}
	echo "------舊版本代碼移動成功"
	adx_old_MD5=$(md5sum $ADX_DIR/${adx_new_version} |  awk '{print $1}')
	echo "代碼回滾後MD5值爲:$adx_old_MD5"
}

fun_rollback_adx_restart(){
	#$ADX_DIR/restart.sh
	systemctl restart httpd
	systemctl restart nginx
	echo "--------後端服務已經啓動"
}

fun_chk_adx_port2(){
#驗證端口存活狀態
	PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'`
	PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'`
    for port in $PORT1 $PORT2;do
        echo "The port is:$port-------端口監聽正常"
    done
}

case $1 in
  direct_deploy)
     fun_copy_direct_code
     fun_chk_direct_code
     fun_deploy_direct_restart
     fun_chk_direct_port1
     ;;
  direct_rollback)
     fun_rollback_direct_code
     fun_rollback_direct_restart
     fun_chk_direct_port2
     ;; 
  adx_deploy)
     fun_copy_adx__code
     fun_chk_adx_code
     fun_deploy_adx_restart
     fun_chk_adx_port1
     ;;
  adx_rollback)
    fun_rollback_adx_code
    fun_rollback_adx_restart
    fun_chk_adx_port2
     ;;
esac

實例4:

#!/bin/bash
#Auth:   liupengju
#TEL:    xxxxx
########部署完成校驗#######

####驗證adserver版本號#############
fun_chk_adx_version(){
	ansible adx -m shell -a 'md5sum   /gnome/adx/gnome-adx-0.0.1-SNAPSHOT-jar-with-dependencies.jar' |awk '{print $1}'|sort |head -n62 |tee version_adx |cat -n
	adx_version=$(ansible adx -m shell -a 'md5sum /gnome/adx/gnome-adx-0.0.1-SNAPSHOT-jar-with-dependencies.jar' |awk '{print $1}'|sort |tail -n62 |uniq -c|awk '{print $2}')
	echo -e "\e[1;32m新發布的版本號爲:$adx_version\e[0m"
	version1=$(diff metadata  version_adx)
        if [ -z $version1 ];then
    	   echo -e "\e[1;32m代碼部署成功 \e[0m"
	else
    	   echo -e "\e[1;31m請檢查錯誤  \e[0m"
	fi
}

####驗證directAd版本號############
fun_chk_direct_version(){	
        ansible adx -m shell -a ' md5sum   /gnome/directAd/direct-ad-0.0.1-SNAPSHOT-jar-with-dependencies.jar'|awk '{print $1}'|sort |head -n62 |tee version_direct |cat -n
        direct_version=$(ansible adx -m shell -a 'md5sum /gnome/directAd/direct-ad-0.0.1-SNAPSHOT-jar-with-dependencies.jar'|awk '{print $1}'|sort |tail -n62 |uniq -c|awk '{print $2}')
        echo -e "\e[1;32m新發布的版本號爲:$direct_version\e[0m"
        version2=$(diff metadata  version_direct)
        if [ -z $version2 ];then
           echo -e "\e[1;32m代碼部署成功 \e[0m"
        else
           echo -e "\e[1;31m請檢查錯誤  \e[0m"
        fi
}

###驗證8080端口狀態###############
fun_chk_8080_port(){
 	chk_ip_8080=$(ansible adx -m shell -a ' netstat -ntulp |grep 8080' |awk '{print $1}' |egrep "[0-9]+\.*" |sort | tee data_8080.bak |cat -n)
	DIR_8080=$(diff metadata  data_8080.bak)
	if [ -z $DIR_8080 ];then
    	   echo -e "\e[1;32m端口檢查成功,端口號:8080 \e[0m"
	else
    	   echo -e "\e[1;31m請檢查錯誤  \e[0m"
	fi
}

####驗證8182端口狀態#############
fun_chk_8182_port(){
	chk_ip_8182=$(ansible adx -m shell -a ' netstat -ntulp |grep 8182' |awk '{print $1}' |egrep "[0-9]+\.*" |sort |tee data_8182.bak |cat -n)
	DIR_8182=$(diff metadata  data_8182.bak)
	if [ -z $DIR_8182 ];then 
	    echo -e "\e[1;32m端口檢查成功,端口號:8182 \e[0m"
	else
	    echo -e "\e[1;31m請檢查錯誤  \e[0m"
	fi
}

case $1 in
     adx)
       fun_chk_adx_version
       fun_chk_8080_port
       fun_chk_8182_port
       ;;
     direct)
       fun_chk_direct_version
       fun_chk_8080_port
       fun_chk_8182_port
       ;;
esac

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章