函数定义和使用
Linux Shell 中的函数和大多数编程语言中的函数一样
将相似的任务或代码封装到函数中,供其他地方调用
语法格式
方法 | 格式内容 |
方法一 | name() { command1 command2 … conmandn } |
方法二 | function name { command1 command2 … commandn } |
#!/bin/bash # 方法一 test() { echo "test function"; } # 方法二 function greeting { echo "hello,Zhangsan"; } test greeting
输出
test function hello,Zhangsan
例子
写一个监控nginx的脚本;如果Nginx服务宕掉,则该脚本可以检测到并将进程启动;如果正常运行,则不做任何处理。
# nginx_daemon.sh #!/bin/bash # 获取当前脚本运行的子id,防止 ps 命令误认 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 3 else systemctl start nginx echo "Nginx is down,Start it ..." fi done # bash > nohup sh nginx_ daemon. sh & [1] 76378 > tail -f nohup.out Nginx is running well Nginx is running well Nginx is running well Nginx is running well
直接使用函数名调用,可以将其想象成 Shell 中的一条命令
函数内部可以直接使用参数$1、$2…、$n
函数传参
调用格式
# name 为函数 name xxx xxx > function greeting > { > echo "hello,$1" > } > greeting chendasheng hello chendasheng
例子
写一个脚本,该脚本可以实现计算器的功能,可以进行 +、-、*、/ 四种计算。
# example3.sh #!/bin/bash function calculate { case "$2" in +) echo "`expr $1 + $3`"; ;; -) echo "`expr $1 - $3`"; ;; \*) echo "`expr $1 \* $3`"; ;; /) echo "`expr $1 / $3`"; ;; esac } calculate $1 $2 $3 # bash > sh example3.sh 5 + 6 11 > sh example3.sh 100 / 6 16
函数返回值
方法 | 函数 |
方法一 | return |
方法二 | echo |
使用 return 返回值
- 使用return返回值,只能返回 1-255 的整数
- 函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回 0 或 1 ; 0 表示成功, 1 表示失败
使用echo返回值
- 使用echo可以返回任何字符串结果
- 通常用于返回数据,比如一个字符串值或者列表值
例子
Nginx 函数引用返回值
#!/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 else return 1 fi } is_nginx_running && echo "Nginx is running" || echo "Nginx is stoped"
局部变量和全局变量
全局变量
- 不做特殊声明, Shell中变量都是全局变量
大型脚本程序中函数中慎用全局变量
局部变量
- 定义变量时,使用local关键字
- 函数内和外若存在同名变量,则函数内部变量覆盖外部变量
例子
# example5.sh #!/bin/bash var1="Hello world" function test { var2=87 local var3=86 echo $var3 } echo $var1 echo $var2 echo $var3 test echo $var1 echo $var2 echo $var3 function test1 { echo $var2 echo $var3 } test1
输出
> sh example5.sh Hello world 86 Hello world 87 87
函数库
为什么要定义函数库,
- 经常使用的重复代码封装成函数文件
- 一般不直接执行,而是由其他脚本调用
例子
定义一个函数库,该函数库实现以下几个函数:
- 加法函数 add
- 减法函数 reduce
- 乘法函数 multiple
- 除法函数 divide
- 打印系统运行情况的函数sys_load,该函数可以显示内存运行情况,磁盘使用情况
# base_function.lib 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 Info" echo df -h echo } # example6.sh #!/bin/bash . /Users/chendashengpc/code/shell/advanced-usage-of-function/base_function.lib add 1 3 reduce 3 4 multiple 7 8 divide 9 10 sys_load
输出
4 -1 56 0 Memory Info total used free shared buff/cache available Mem: 7678 2371 461 84 4844 4924 Swap: 0 0 0 Disk Info Filesystem Size Used Avail Use% Mounted on devtmpfs 3.8G 0 3.8G 0% /dev tmpfs 3.8G 16K 3.8G 1% /dev/shm tmpfs 3.8G 572K 3.8G 1% /run tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup /dev/vda1 79G 19G 57G 26% / tmpfs 768M 0 768M 0% /run/user/1001 tmpfs 768M 0 768M 0% /run/user/0
经验之谈
- 库文件名的后缀是任意的,但一般使用 .lib
- 库文件通常没有可执行选项
- 库文件无需和脚本在同级目录,只需在脚本中引用时指定
- 第一行一般使用 #!/bin/echo 输出警告信息,避免用户执行