shell編程系列6--shell中的函數 1.函數介紹 linux shell中的函數和大多數編程語言中的函數同樣 將類似的任務或者代碼封裝到函數中,供其餘地方調用 語法格式 第一種格式 name() { command1 command2 ...... commondn } 第二種格式 function name { command1 command2 ...... commondn } 2.調用函數 直接使用函數名調用,能夠將其想象成shell中的一條命令 函數內部能夠直接使用參數 $1、$2...$n 調用函數:function_name $1 $2 shell終端中定義函數 [root@es01 shell]# test() > { > echo "test function" > } [root@es01 shell]# [root@es01 shell]# test test function [root@es01 shell]# function greeting > { > echo "hello,zhangsan" > } [root@es01 shell]# greeting hello,zhangsan 練習;nginx的守護進程 [root@es01 shell]# cat nginx_daemon.sh #!/bin/bash # # 獲取腳本子進程的pid,若是腳本名稱中帶nginx,也會當成nginx進程 this_pid=$$ while true do ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null if [ $? -eq 0 ];then echo "Nginx is running well" sleep 5 else systemctl start nginx echo "Nginx is down,Start it..." fi done [root@es01 shell]# nohup sh nginx_daemon.sh & [1] 97855 [root@es01 shell]# nohup: ignoring input and appending output to ‘nohup.out’ [root@es01 shell]# tail -f nohup.out Nginx is running well Nginx is running well Nginx is running well Nginx is running well 4.向函數傳遞參數 高級語言傳參 int example_1(int arg1,int arg2) { arg1=arg2 ... ... return null } 高級語言函數調用 int num1=10; int num2=20; 調用函數形式一:int num3=example_1(num1,num2); 調用函數形式二: int num4; num4=example_1(num1,num2); shell中傳參 function name { echo "Hello $1" echo "Hello $2" } shell中函數調用 函數調用:name Lily Allen [root@es01 shell]# function greeting > { > echo "hello zhangsan" > } [root@es01 shell]# greeting hello zhangsan # 調用參數 [root@es01 shell]# function greeeting > { > echo "hello $1" > } [root@es01 shell]# greeeting jack hello jack [root@es01 shell]# greeeting tom hello tom 向函數傳遞參數: 函數傳參和給腳本傳參相似,都是使用$1 $2 $3 $4 $5 $6 $7這種方式 例子1: 需求描述:寫一個腳本,該腳本能夠實現計算器的功能,能夠進行+-*/四種運算。 例如:sh calculate.sh 30 + 40 | sh calucate.sh 30 - 40 [root@es01 shell]# cat calucate.sh #!/bin/bash # function calcu { case $2 in +) echo "`expr $1 + $3`" ;; -) echo "`expr $1 - $3`" ;; \*) echo "`expr $1 \* $3`" ;; /) echo "`expr $1 / $3`" ;; esac } calcu $1 $2 $3 [root@es01 shell]# sh calucate.sh 20 + 30 50 [root@es01 shell]# sh calucate.sh 20 - 30 -10 5.函數的返回值 方法一 return 方法二 echo 使用return返回值 使用return返回值,只能返回1-255的整數 函數使用return返回值,一般只是用來供其餘地方調用獲取狀態,所以一般僅返回0或1;0表示成功,1表示失敗 # 判斷nginx進程是否存在 [root@es01 shell]# cat nginx.sh #!/bin/bash # this_pid=$$ function is_nginx_running { ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null if [ $? -eq 0 ];then return 0 else return 1 fi } is_nginx_running && echo "nginx is running" || echo "nginx is stopped" [root@es01 shell]# sh nginx.sh nginx is running [root@es01 shell]# systemctl stop nginx [root@es01 shell]# sh nginx.sh nginx is stopped [root@es01 shell]# sh -x nginx.sh + this_pid=101185 + is_nginx_running + ps -ef + grep nginx + grep -v grep + grep -v 101185 + '[' 1 -eq 0 ']' + return 1 + echo 'nginx is stopped' nginx is stopped 使用echo返回值 使用echo能夠返回任何字符串結果 一般用於返回數據,好比一個字符串值或者列表值 # 獲取系統中的用戶 [root@es01 shell]# cat get_sys_user.sh #!/bin/bash # # 獲取系統全部的用戶名 function get_users { users=`cat /etc/passwd | cut -d: -f1` echo $users } # 定義一個變量將獲取用戶列表賦值給這個變量 user_list=`get_users` index=1 for u in $user_list do echo "the $index user is : $u" index=$(($index+1)) done [root@es01 shell]# sh get_sys_user.sh the 1 user is : root the 2 user is : bin the 3 user is : daemon the 4 user is : adm the 5 user is : lp the 6 user is : sync the 7 user is : shutdown the 8 user is : halt the 9 user is : mail the 10 user is : operator the 11 user is : games the 12 user is : ftp the 13 user is : nobody the 14 user is : systemd-network the 15 user is : dbus the 16 user is : polkitd the 17 user is : sshd the 18 user is : postfix the 19 user is : ajie the 20 user is : chrony the 21 user is : elasticsearch the 22 user is : nginx 6.shell函數中的局部變量和全局變量 不作特殊聲明,shell中變量都是全局變量 大型腳本程序函數中慎用全局變量 局部變量: 在函數內部定義局部變量時,使用local關鍵字 函數內和函數外若同時存在變量,函數內部變量會覆蓋外部變量 # [root@es01 shell]# cat var.sh #!/bin/bash # var1="Hello world" function test { var2=87 } echo $var1 echo $var2 # 由於函數test沒有被調用,因此變量 $var2 沒有生效,爲空 [root@es01 shell]# sh var.sh Hello world [root@es01 shell]# # 調用test函數後,$var2就變成了全局變量 [root@es01 shell]# cat var.sh #!/bin/bash # var1="Hello world" function test { var2=87 } echo $var1 echo $var2 test # 調用test函數後,$var2就變成了全局變量 echo $var1 echo $var2 [root@es01 shell]# sh var.sh Hello world Hello world 87 # 在函數中也能夠調用全局變量 [root@es01 shell]# cat var.sh #!/bin/bash # var1="Hello world" function test { var2=87 } echo $var1 echo $var2 test echo $var1 echo $var2 function test1 { echo $var2 } test1 [root@es01 shell]# sh var.sh Hello world Hello world 87 87 # 若是函數中聲明瞭局部變量,當函數執行完成後局部變量就會被銷燬 [root@es01 shell]# cat var.sh #!/bin/bash # var1="Hello world" function test { local var2=87 # 局部變量,只在函數內部生效,生命週期只在函數內部 } test echo $var1 echo $var2 [root@es01 shell]# sh var.sh Hello world [root@es01 shell]# 7.函數庫 爲何須要定義函數庫? 常常使用的重複代碼能夠封裝成函數文件,功能函數,程序工具 函數庫文件通常不直接執行,而是由其餘腳本調用 函數庫示例: 定義一個函數庫,該函數庫實現如下幾個函數: 1.加法函數add add 12 89 2.減法函數reduce reduce 90 30 3.乘法函數multiple multiple 12 10 4.除法函數divide divide 9 3 5.打印系統運行狀況的函數sys_load,該函數能夠顯示內存運行狀況,磁盤使用狀況 # 定義庫函數 [root@es01 shell]# cat lib/base_function function add { echo "`expr $1 + $2`" } function reduce { echo "`expr $1 - $2`" } function multiple { echo "`expr $1 \* $2`" } function divide { echo "`expr $1 / $2`" } function sys_load { echo "Memory info" echo free -m echo echo "Disk Usage" echo df -h echo } # 測試庫函數 [root@es01 shell]# . lib/base_function [root@es01 shell]# sys_load Memory info total used free shared buff/cache available Mem: 3773 123 3300 11 348 3389 Swap: 2047 0 2047 Disk Usage Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 49G 3.3G 46G 7% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 1.9G 12M 1.9G 1% /run tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/sda1 297M 125M 172M 43% /boot /dev/mapper/centos-data 49G 33M 49G 1% /data tmpfs 378M 0 378M 0% /run/user/0 # 調用庫函數 [root@es01 shell]# cat calculate.sh #!/bin/bash # # 引入庫函數,寫絕對路徑避免出錯 . /data/shell/lib/base_function add 12 23 reduce 90 30 multiple 12 12 divide 12 2 經驗之談: 庫文件名的後綴是任意的,但通常使用.lib 庫文件一般沒有可執行權限 庫文件無需和腳本放在同級目錄,只須要在腳本中引用時指定 第一行通常使用#!/bin/echo,輸出警告信息,避免用戶執行