函数定义和使用

函数介绍

  • Linux Shell中的函数和大多数编程语言中的函数一样
  • 将相似的任务或代码封装到函数中,供其他地方调用

语法格式

  • 第一种格式

    1
    2
    3
    4
    5
    6
    7
    name()
    {
    command1
    command2
    ...
    comandn
    }
  • 第二种格式

    1
    2
    3
    4
    5
    6
    7
    function name
    {
    command1
    command2
    ...
    comandn
    }

如何调用函数

  • 直接使用函数名调用,可以将其想象成Shell中的一条命令
  • 函数内部可以直接使用参数$1、$2...$n
  • 调用函数:function_name $1 $2

练习

需求描述:写一个监控nginx的脚本:如果nginx服务宕掉,则该脚本可以检测到并将进程启动;如果正常运行,则不做任何操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
#

this_pid=$$ # 获取当前进程的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"
else
systemctl start nginx
echo "Nginx is down, start it ..."
fi
done

向函数传递参数

Shell中函数调用

函数调用:name param1 param2 …

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# function hello
> {
> echo "Hello world"
> }
[root@localhost ~]# hello
Hello world
[root@localhost ~]# function hello
> {
> echo "Hello, $1"
> }
[root@localhost ~]# hello Jack
Hello, Jack

练习

需求描述:写一个脚本,该脚本可以实现计算器的功能,可以进行+-*/四种计算。

例如:sh calculate.sh 30 + 40 | sh calculate.sh 30 - 40

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/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

函数返回值

返回值方式

方法一 return
方法二 echo

使用return返回值

  • 使用return返回值,只能返回1-255的整数
  • 函数使用用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败

使用echo返回值

  • 使用echo可以返回任何字符串结果
  • 通常用于返回数据,比如一个字符串值或者列表值

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
#!/bin/bash
#

# 获取当前的pid
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 # 执行失败返回1
fi
}

# 函数调用
is_nginx_running && echo "Nginx is running" || echo "Nginx is stoped"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
#

function get_users
{
users=`cat /etc/passwd | cut -d: -f 1`
echo $users
}

# 函数调用
user_list=`get_users`

index=1
for u in $user_list
do
echo "The $index user is : $u"
index=$(($index+1))
done

局部变量和全局变量

全局变量

  • 不做特殊声明,Shell中变量都是全局变量
  • Tips:大型脚本程序中函数中慎用全局变量

局部变量

  • 定义变量时,使用local关键字
  • 函数内和外若存在同名变量,则函数内部变量覆盖外部变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash
#

var1="Hello World"

function test
{
var2=87
local var3=55 #局部变量
echo $var3
}
echo $var1
echo $var2 # 不会输出

# 函数调用
test

echo $var1
echo $var2
echo $var3 # 不会输出

function test1
{
echo $var2 # 没有关键字定义,则是全局变量
echo $var3 # 不会输出
}

#函数调用
test1

函数库

为什么要定义函数库

  • 经常使用的重复代码封装成函数文件
  • 一般不直接执行,而是由其他脚本调用

练习

函数库:定义一个函数库,该函数库实现以下几个函数:

  1. 加法函数add
  2. 减法函数reduce
  3. 乘法函数multiple
  4. 除法函数divide
  5. 打印系统运行情况的函数sys_load,该函数可以显示内存运行情况

函数库base_function.lib

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/echo

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
}

函数calculate.sh调用函数库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
#

# 引入函数库,需要绝对路径
. /home/lvjing/base_function.lib

add 12 23

reduce 90 30

multiple 12 12

divide 12 12

sys_load

经验之谈

  • 库文件名的后缀是任意的,但一般使用.lib
  • 库文件通常没有可执行选项
  • 库文件无需和脚本在同级目录,只需在脚本中引用时指定
  • 第一行一般使用#!/bin/echo,输出警告信息,避免用户执行