shell编程系列6--shell中的函数
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,输出警告信息,避免用户执行