服務器端操作學習大綱
一、函數基礎
需求場景
- 在shell腳本的編寫過程中,我們經常會遇到一些功能代碼場景:多條命令組合在一起,實現一個特定的功能場景邏輯、一些命令在腳本內部的多個位置頻繁出現。在這些場景的代碼量往往不多,但是頻繁使用的話,會導致腳本的整體邏輯脈絡比較松散和框架散亂,所以我們需要一種腳本邏輯,不僅僅能夠滿足松散代碼的功能目的,還能精簡重復的代碼。函數就是來滿足這種場景的解決方案 – 而函數,也是所謂的面向對象編程的一種表現樣式
什么是函數:
- 所謂的函數,本質上就是一段能夠滿足特定功能的代碼塊。一旦定義好函數代碼后,我們就可以在腳本的很多位置隨意的使用。
定義功能代碼塊的動作叫函數定義,使用函數代碼的動作叫函數調用
函數的優勢:
- 代碼模塊化,調用方便,節省內存
- 代碼模塊化,代碼量少,排錯簡單
- 代碼模塊化,可以改變代碼的執行順序
二、定義簡單函數:
2.1.基本語法
- 樣式1:定義函數:
function 函數名{ 函數體 }
- 樣式2:簡約格式
函數名() { 函數體
}
2.2.注意事項:
- function 的作用和 () 的作用是一樣的,都是定義一個函數
- 函數的名稱是自定義的,而且在腳本范圍內必須唯一
- 函數體內是普通的能夠正常執行的命令,命令的執行流程符合順序邏輯
2.3.函數調用:
- 函數名
- 注意:
- 函數名出現在任何位置,就代表在該位置調用函數內代碼塊的執行
- 函數名一般在函數定義后調用,否則的話會發生報錯
2.4.簡單實踐:
實踐1-標準函數的實踐
- 1.簡單函數的定義與調用:
[root@localhost ~]# cat function_simple_test.sh
#!/bin/bash
# 定制一個函數,提示腳本的使用方式
function Usage {echo -e "\e[31m腳本的使用幫助信息: xxx\e[0m"
}# 定制腳本使用邏輯
if [ $# -eq 1 ]
thenecho "您輸入的腳本參數是1個"
elseUsage
fi
腳本執行效果
[root@localhost ~]# /bin/bash function_simple_test.sh
腳本的使用幫助信息: xxx
[root@localhost ~]# /bin/bash function_simple_test.sh aa
您輸入的腳本參數是1個
[root@localhost ~]# /bin/bash function_simple_test.sh aa bb
腳本的使用幫助信息: xxx
實踐2-變種函數的實踐
[root@localhost ~]# cat function_simple_test2.sh
#!/bin/bash
# 功能:簡單函數的定義和調用# 定制一個函數,提示腳本的使用方式
Usage() {echo -e "\e[31m腳本的使用幫助信息: xxx\e[0m"
}# 定制腳本使用邏輯
if [ $# -eq 1 ]
thenecho "您輸入的腳本參數是1個"
elseUsage
fi
腳本執行效果
[root@localhost ~]# /bin/bash function_simple_test2.sh
腳本的使用幫助信息: xxx
[root@localhost ~]# /bin/bash function_simple_test2.sh aa
您輸入的腳本參數是1個
[root@localhost ~]# /bin/bash function_simple_test2.sh aa bb
腳本的使用幫助信息: xxx
實踐3-函數的調用順序和名稱唯一實踐
- 功能:簡單函數的定義和調用
[root@localhost ~]# cat function_simple_test3.sh
#!/bin/bash# 定制一個函數,提示腳本的使用方式
Usage() {echo -e "\e[31m腳本的使用幫助信息: xxx\e[0m"
}
echo "第一次調用效果: "
Usage# 定制同名的函數,提示腳本的使用方式
Usage() {echo -e "\e[31m腳本的使用幫助信息-------: xxx\e[0m"
}# 定制腳本使用邏輯
if [ $# -eq 1 ]
then# 調用一個后面才會生成的函數func
elseUsage
fi# 定制一個函數
func() {echo "您輸入的腳本參數是1個"
}
- 2.結果:
[root@localhost ~]# /bin/bash function_simple_test3.sh
第一次調用效果:
腳本的使用幫助信息: xxx
腳本的使用幫助信息-------: xxx
[root@localhost ~]# /bin/bash function_simple_test3.sh a
第一次調用效果:
腳本的使用幫助信息: xxx
function_simple_test3.sh:行18: func: 未找到命令
- 3.總結:
- 函數名稱重復的話,會導致同名函數被覆蓋
- 函數在沒有定義前調用的話,會導致異常報錯
三、定義傳參函數
3.1.簡介
- 簡單的函數定義和調用的實踐,我們只能實現固定內容的輸出,不具有靈活性。其實函數作為shell腳本內部的小腳本也支持腳本傳參的一系列能力
3.2.定義傳參函數:
a.語法:
函數名() { 函數體 ${變量名} }
b.注意:
- 注意:函數體內通過 ${變量名} 來實現函數體的功能通用性
3.3.調用傳參函數:
a.語法:
函數名 參數
b.注意:
- 函數在調用的時候,接收一些參數并傳輸到函數體內部
3.4.案例:
實踐1-傳參函數實踐
- 傳參函數定義和調用
[root@localhost ~]# cat function_arg_input.sh
#!/bin/bash
# 功能:傳參函數定義和調用# 定制數據運算的函數
add_func() {echo $(( $1 + $2 ))
}
sub_func() {echo $(( $1 - $2 ))
}
mul_func() {echo $(( $1 * $2 ))
}
div_func() {echo $(( $1 / $2 ))
}echo -n "4+3="; add_func 4 3
echo -n "4-3="; sub_func 4 3
echo -n "4*3="; mul_func 4 3
echo -n "4/3="; div_func 4 3
- 2.腳本執行效果
[root@localhost ~]# /bin/bash function_arg_input.sh
4+3=7
4-3=1
4*3=12
4/3=1
3.5.腳本傳參
a.簡介
- 傳參函數定義和調用的實踐,實現了函數層面的靈活性,但是它受到函數調用本身的參數限制。往往這些參數我們需要在腳本執行的時候傳遞進去,從而實現腳本功能的靈活性。
b.基本語法
- 定義函數:
函數名() { 函數體 ${函數參數} }
- 調用函數:
函數名 ${腳本參數}
- 腳本執行:
/bin/bash /path/to/scripts.sh arg
c.注意:
- 由于腳本內部調用腳本參數和函數體內調用函數參數都遵循位置變量的使用,所以,一般情況下,我們會借助于臨時變量的方式接收各自的參數,從而避免引起誤會
d.實踐1-腳本傳參函數實踐
查看腳本內容
[root@localhost ~]# cat function_arg_scripts.sh
#!/bin/bash
# 功能:腳本傳參函數調用# 定制數據運算的函數
add_func() {echo $(( $1 + $2 ))
}
sub_func() {echo $(( $1 - $2 ))
}
mul_func() {echo $(( $1 * $2 ))
}
div_func() {echo $(( $1 / $2 ))
}[ $# -ne 2 ] && echo "必須傳遞兩個數字參數" && exit
echo -n "$1+$2="; add_func $1 $2
echo -n "$1-$2="; sub_func $1 $2
echo -n "$1*$2="; mul_func $1 $2
echo -n "$1/$2="; div_func $1 $2注意:這種簡單的腳本傳參函數調用,導致大量的位置參數,容易引起混亂,需要改造
- 2.腳本執行效果
[root@localhost ~]# /bin/bash function_arg_scripts.sh
必須傳遞兩個數字參數
[root@localhost ~]# /bin/bash function_arg_scripts.sh 5 4
5+4=9
5-4=1
5*4=20
5/4=1
e.實踐2-實踐2-腳本傳參函數進階實踐
查看腳本內容
[root@localhost ~]# cat function_arg_scripts2.sh
#!/bin/bash
# 功能:傳參函數定義和調用# 接收腳本傳參
arg1=$1
arg2=$2
# 定制數據運算的函數
add_func() {num1=$1num2=$2echo $(( ${num1} + ${num2} ))
}
sub_func() {num1=$1num2=$2echo $(( ${num1} - ${num2} ))
}
mul_func() {num1=$1num2=$2echo $(( ${num1} * ${num2} ))
}
div_func() {num1=$1num2=$2echo $(( ${num1} / ${num2} ))
}[ $# -ne 2 ] && echo "必須傳遞兩個數字參數" && exit
echo -n "${arg1}+${arg2}="; add_func ${arg1} ${arg2}
echo -n "${arg1}-${arg2}="; sub_func ${arg1} ${arg2}
echo -n "${arg1}*${arg2}="; mul_func ${arg1} ${arg2}
echo -n "${arg1}/${arg2}="; div_func ${arg1} ${arg2}
腳本執行效果
[root@localhost ~]# /bin/bash function_arg_scripts2.sh
必須傳遞兩個數字參數
[root@localhost ~]# /bin/bash function_arg_scripts2.sh 7 5
7+5=12
7-5=2
7*5=35
7/5=1
四、函數退出
4.1.簡介
- 我們可以將函數代碼塊,看成shell腳本內部的小型腳本,所以說函數代碼塊也會有執行狀態返回值。對于函數來說,它通常支持兩種種狀態返回值的樣式
- 樣式1-默認的退出狀態:
- 默認情況下,函數的退出狀態是函數體內的最后一條命令的退出狀態,可以通過 $? 來獲取
- 樣式2-return定制狀態返回值:
- 在函數體內部,通過return定制狀態返回值的內容
4.2.注意:
- return的狀態返回值必須盡快使用,否則會被其他return的值覆蓋
- return的狀態返回值必須在 0-255,否則失效
4.3.簡單實踐:
實踐1-默認退出狀態
[root@localhost ~]# cat function_exit_status1.sh
#!/bin/bash
# 功能:函數默認狀態返回值# 定制成功運行的函數
ok_func() {echo -e "\e[31m腳本的使用幫助信息: xxx\e[0m"
}
# 定制一個運行失敗的函數
err_func() {666666
}
# 定制腳本使用邏輯
if [ $# -eq 1 ]
thenerr_funcecho "錯誤函數的執行狀態返回值: " $?
elseok_funcecho "成功函數的執行狀態返回值: " $?
fi
腳本執行效果
[root@localhost ~]# /bin/bash function_exit_status1.sh
腳本的使用幫助信息: xxx
成功函數的執行狀態返回值: 0
[root@localhost ~]# /bin/bash function_exit_status1.sh aa
function_exit_status1.sh:行10: 666666: 未找到命令
錯誤函數的執行狀態返回值: 127
[root@localhost ~]# lll; echo $?
bash: lll: 未找到命令
127
結果顯示:對于異常的函數來說,默認的狀態返回值有安全隱患
實踐2-return定制函數的返回值實踐
[root@localhost ~]# cat function_exit_status2.sh
#!/bin/bash
# 功能:return定制函數狀態返回值# 定制成功運行的函數
ok_func() {echo -e "\e[31m腳本的使用幫助信息: xxx\e[0m"# 定制超范圍的狀態返回值return 666
}
# 定制一個運行失敗的函數
err_func() {666666# 定制狀態返回值return 222
}
# 定制腳本使用邏輯
if [ $# -eq 1 ]
thenerr_funcecho "錯誤函數的執行狀態返回值: " $?
elseok_funcecho "成功函數的執行狀態返回值: " $?
fi
腳本執行效果
[root@localhost ~]# /bin/bash function_exit_status2.sh
腳本的使用幫助信息: xxx
成功函數的執行狀態返回值: 154
[root@localhost ~]# /bin/bash function_exit_status2.sh aa
function_exit_status2.sh:行12: 666666: 未找到命令
錯誤函數的執行狀態返回值: 222
結果顯示:return的狀態返回值范圍必須滿足要求
五、綜合案例
5.1.信息采集
- 腳本實踐-采集系統負載信息
[root@localhost ~]# cat function_systemctl_load.sh
#!/bin/bash
# 功能:采集系統負載信息
# 版本:v0.3# 定制資源類型
resource_type=(CPU MEM)# 定制cpu信息輸出函數
cpu_info() {cpu_attribute=(1 5 15)cpu_load=($(uptime | tr -s " " | cut -d " " -f 11-13 | tr "," " "))echo -e "\e[31m\t系統CPU負載信息\e[0m"echo -e "\e[32m================================"for index in ${!cpu_attribute[@]}doecho "CPU ${cpu_attribute[$index]} min平均負載為: ${cpu_load[$index]}" doneecho -e "================================\e[0m"
}
# 獲取內存相關屬性信息
mem_info() {free_attribute=(總量 使用 空閑)free_info=($(free -m | grep Mem | tr -s " " | cut -d " " -f 2-4))echo -e "\e[31m\t系統內存負載信息\e[0m"echo -e "\e[32m================================"for index in ${!free_attribute[@]}doecho "內存 ${free_attribute[$index]} 信息為: ${free_info[$index]} M" doneecho -e "================================\e[0m"
}# 服務的操作提示
echo -e "\e[31m---------------查看資源操作動作---------------1: CPU 2: MEM
-------------------------------------------"'\033[0m'
# 選擇服務操作類型
while true
doread -p "> 請輸入要查看的資源信息類型: " resource_idechocase ${resource_type[$resource_id-1]} in"CPU")cpu_info;;"MEM")mem_info;;*)echo -e "\e[31m\t請輸入有效的信息類型\e[0m";;esac
done
- 2.測試:
腳本使用效果
[root@localhost ~]# /bin/bash function_systemctl_load.sh
---------------查看資源操作動作---------------1: CPU 2: MEM
-------------------------------------------
> 請輸入要查看的資源信息類型: 1系統CPU負載信息
================================
CPU 1 min平均負載為: 0.00
CPU 5 min平均負載為: 0.01
CPU 15 min平均負載為: 0.05
================================
> 請輸入要查看的資源信息類型: 2系統內存負載信息
================================
內存 總量 信息為: 3770 M
內存 使用 信息為: 237 M
內存 空閑 信息為: 3290 M
================================
> 請輸入要查看的資源信息類型: 3請輸入有效的信息類型
> 請輸入要查看的資源信息類型: ^C
[root@localhost ~]#
5.2.環境部署
a.需求
- 定制kubernetes環境部署管理的功能腳本改造
- 功能函數實現
- 擴充while循環執行功能
- 增加q退出環境功能
b.腳本內容
- 查看腳本內容
[root@localhost ~]# cat function_kubernetes_manager.sh
#!/bin/bash
# 功能:定制kubernetes環境部署管理的功能
# 版本:v0.2# 定制數組變量
env_array=(base ha k8s_base master slave)# 監控平臺的信息提示
menu(){echo -e "\e[31m 歡迎使用kubernetes部署平臺"echo -e "\e[32m-----------請選擇部署階段-----------"echo -e " 1: 基礎環境部署"echo -e " 2: 高可用環境部署"echo -e " 3: kubernetes基礎環境部署"echo -e " 4: 主角色環境部署"echo -e " 5: 從角色環境部署"echo -e " q: 退出"echo -e "----------------------------------\033[0m"
}
# 定制基礎環境
os_base_func(){echo -e "\e[31m開始基礎環境部署..."echo "1 執行跨主機免密碼操作"echo "2 執行時間同步操作"echo "3 執行內核配置操作"echo -e "4 執行容器私有倉庫部署操作\e[0m"
}# 定制高可用環境
ha_func(){echo -e "\e[31高可用環境部署..."echo "1 執行高可用環境部署操作"echo -e "2 執行負載均衡環境部署操作\e[0m"
}# 定制k8s基礎環境
k8s_base_func(){echo -e "\e[31mkubernetes基礎環境部署..."echo "1 執行證書管理操作"echo "2 執行etcd環境部署操作"echo -e "3 執行集群證書配置操作\e[0m"
}# 定制主角色環境
master_func(){echo -e "\e[31m主角色環境部署..."echo "1 執行apiserver環境部署操作"echo "2 執行scheduler環境部署操作"echo "3 執行controller環境部署操作"echo "4 執行認證配置操作"echo "5 執行容器環境部署操作"echo "6 執行kubelet環境部署操作"echo -e "7 執行kube-proxy環境部署\e[0m"
}
# 定制從角色環境
slave_func(){echo -e "\e[31m主角色環境部署..."echo "1 執行容器環境部署操作"echo "2 執行kubelet環境部署操作"echo -e "3 執行kube-proxy環境部署\e[0m"
}
# 定制錯誤提示信息
usage_func(){echo -e "\e[31m請輸入有效的功能場景標識\e[0m"
}# 腳本內容的判斷
while true
do# 定制業務邏輯menuread -p "請輸入功能標識: " env_idif [ ${env_id} == "q" ];thenexitelse# 執行配套業務邏輯case "${env_array[$env_id-1]}" in"base")os_base_func;;"ha")ha_func;;"k8s_base")k8s_base_func;;"master")master_func;;"slave")slave_func;;*)usage_func;;esacfi
done
- 2.測試:
[root@localhost ~]# /bin/bash function_kubernetes_manager.sh歡迎使用kubernetes部署平臺
-----------請選擇部署階段-----------1: 基礎環境部署2: 高可用環境部署3: kubernetes基礎環境部署4: 主角色環境部署5: 從角色環境部署q: 退出
----------------------------------
請輸入功能標識: 6
請輸入有效的功能場景標識歡迎使用kubernetes部署平臺
-----------請選擇部署階段-----------1: 基礎環境部署2: 高可用環境部署3: kubernetes基礎環境部署4: 主角色環境部署5: 從角色環境部署q: 退出
----------------------------------
請輸入功能標識: 5
主角色環境部署...
1 執行容器環境部署操作
2 執行kubelet環境部署操作
3 執行kube-proxy環境部署歡迎使用kubernetes部署平臺
-----------請選擇部署階段-----------1: 基礎環境部署2: 高可用環境部署3: kubernetes基礎環境部署4: 主角色環境部署5: 從角色環境部署q: 退出
----------------------------------
請輸入功能標識: q