Shell脚本—函数
文章目录
- Shell脚本—函数
- 1.函数基本概述
- 2.函数的基本语法
- 3.函数的传参
- 4.函数状态返回
- 5.函数练习
- 6.shell 数组
- 7.数组的遍历与循环
1.函数基本概述
1.什么是shell函数
函数就是一堆命令的集合,用来完成特定功能的代码块
2.为什么要使用函数
比如:我们经常需要使用判断功能,完全可以将其封装为一个函数,这样在写程序过程中可以在任何地方调用该函数,不必重复编写,这样能减少代码冗余,可读性更强
2.函数的基本语法
1.定义shell函数,可以通过以下两种方式进行定义
#方式1:
name(){
command1
command2
....
commandN
}
#方式2:
function name {
command1
command2
...
commandN
}
2.如何调用函数,直接使用函数名调用(可以理解为shell的一条命令)
[root@manage functions]# fun () { echo "123"; }
#调用函数
[root@manage functions]# fun
123
3.函数的传参
在函数内部也可以使用参数$1 $2 …,调用函数function_name $1 $2 …
1.函数中传递参数
[root@manage functions]# fun () { echo "123 $1"; }
#调用
[root@manage functions]# fun 456
123 456
2.函数中接收多个参数
[root@manage functions]# fun1 () { echo "123 $1 $2 $3 $4"; }
[root@manage functions]# fun1 11 22 33 44
123 11 22 33 44
需求1:写一个脚本,该脚本可以实现计算器的功能,可以进行+ - * / 四种计算
eg:sh cash.sh 30 + 40 | sh cash.sh 30 -40 | sh cash.sh 30 * 40 | sh cash.sh 30 / 40
[root@manage functions]# cat fun01.sh
#!/bin/bash
fun (){
case $2 in
+)
echo $1 + $3 = $[ $1 + $3 ]
;;
-)
echo $1 - $3 = $[ $1 - $3 ]
;;
x)
echo $1 x $3 = $[ $1 * $3 ]
;;
/)
echo $1 / $3 = $[ $1 / $3 ]
;;
esac
}
fun $1 $2 $3
[root@manage functions]# sh fun.sh 1 + 2
1 + 2 = 3
需求2:写一个nginx启停脚本,把公用部分写为函数
[root@manage functions]# cat fun02.sh
#!/bin/bash
nginx_status (){
systemctl $1 nginx
if [ $? -eq 0 ];then
echo "nginx $1 ok"
else
echo "nginx $1 err"
exit
fi
}
case $1 in
start)
nginx_status $1
;;
stop)
nginx_status $1
;;
restart)
nginx_status $1
;;
*)
echo "USAGE:请输入一个参数: start | stop | restart"
esac
4.函数状态返回
shell的函数返回值,也算是退出的状态,在shell中只有echo、return两种方式
1.return返回值:只能返回1-255的整数,函数使用return返回值,通常只是用来提供其他地方调用获取状态,因此通常返回0或1;0表示成功,1表示失败
2.echo返回值:使用echo可以返回任何字符串结果,通常用于返回数据,比如一个字符串值或者列表值
1.shell函数echo返回字符串结果示例1
#函数实例脚本: echo
echo "The 1 user is : root"
echo "The 2 user is : bin"
[root@manage functions]# cat fun03.sh
#!/bin/bash
get_users () {
user=$(awk -F ":" '{print $1}' /etc/passwd)
echo $user
}
user_list=$(get_users)
index=1
for u in ${user_list}
do
echo "This $index user is :$u"
let index++
done
[root@manage functions]# sh fun03.sh
This 1 user is :root
This 2 user is :bin
This 3 user is :daemon
This 4 user is :adm
This 5 user is :lp
#函数脚本示例:return
[root@manage functions]# cat fun04.sh
#!/bin/bash
file=$1 #定义文件
t_file(){ #函数判断
if [ -f $file ];then
return 0
else
return 1
fi
}
$?
t_file
rc=$?
if [ $rc -eq 0 ];then
echo "该文件存在 $file"
else
echo "该文件不存在 $file"
fi
[root@manage functions]# cat fun05.sh
#!/bin/bash
fun () {
systemctl status nginx &>/dev/null
if [ $? -eq 0 ];then
return 0
else
return 100
fi
}
fun
echo $?
retrun: 主要控制函数的返回值 可以理解是命令执行后的结果
echo: 主要控制函数的返回数据
根据用户传递的服务名称,获取不同服务的状态
[root@manage functions]# cat fun06.sh
#!/bin/bash
is_server_running(){
systemctl status $1 &>/dev/null
if [ $? -eq 0 ];then
return 0
else
return 1
fi
}
#调用函数,并根据函数返回状态码进行输出
is_server_running $1 && echo "$1 is Running" || echo "$1 is stoped"
5.函数练习
需求1:使用函数、循环、case实现系统管理工具箱
Command action
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
[root@manage functions]# cat fun07.sh
#!/bin/bash
meminfo (){
cat <<-EOF
----------------------------
Command action
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
---------------------------
EOF
}
meminfo
while true
do
read -p "请输入你要选择的选项:" Action
case $Action in
h)
help
;;
f)
lsblk
;;
d)
df -h
;;
m)
free -m
;;
u)
uptime
;;
q)
exit 1
;;
*)
continue
esac
done
需求2:使用case、循环、函数、实现JumpServer跳板机功能。
1.用户登陆该服务器则自动执行该脚本。 pass
2.脚本提示可连接主机列表。
3.该脚本无法直接退出。 pass
[root@manager functions]# cat fun11.sh
#!/bin/bash
meminfo(){
cat <<-EOF
-------------------------------
| 1) lb01-172.16.1.5 |
| 2) lb02-172.16.1.6 |
| 3) web01-172.16.1.7 |
| 4) web02-172.16.1.8 |
| h) help |
---------------------------------
EOF
}
meminfo
trap "" HUP INT TSTP
while true
do
read -p "请输入你要登录的主机: " Action
case $Action in
1|lb01)
ssh root@172.16.1.5
;;
2|lb02)
ssh root@172.16.1.6
;;
3|web01)
ssh root@172.16.1.7
;;
4|web02)
ssh root@172.16.1.8
;;
h)
clear
meminfo
;;
exec)
exit
;;
*)
continue
esac
done
需求3:case场景示例,实现多级菜单功能,需要使用到函数、case、循环、if判断、变量
[root@manage functions]# cat fun08.sh
#!/bin/bash
mem_info_1 () {
cat <<-EOF
+-------------------+
| command action |
+-------------------+
| (1) Install Nginx |
| (2) Install PHP |
| (3) Install Mysql |
| (4) quit |
+-------------------+
EOF
}
mem_info_2 () {
cat <<-EOF
+-----------------------+
| nginx-version |
+-----------------------+
| (1) Install Nginx 1.12|
| (2) Install Nginx 1.13|
| (3) Install Nginx 1.14|
| (4) 返回上级菜单 |
+-----------------------+
EOF
}
mem_info_3 () {
cat <<-EOF
+-----------------------+
| php-version |
+-----------------------+
| (1) Install PHP 1.12 |
| (2) Install PHP 1.13 |
| (3) Install PHP 1.14 |
| (4) 返回上级菜单 |
+-----------------------+
EOF
}
mem_info_4 () {
cat <<-EOF
+-----------------------+
| mysql-version |
+-----------------------+
| (1) Install Mysql 1.12|
| (2) Install Mysql 1.13|
| (3) Install Mysql 1.14|
| (4) 返回上级菜单 |
+-----------------------+
EOF
}
while true
do
#打印第一个菜单
mem_info_1
read -p "请输入你要进入的菜单:" mem_1
case $mem_1 in
1)
clear
mem_info_2
while true
do
read -p "请输入要安装的版本:" mem_2
case $mem_2 in
1)
echo "Install Nginx 1.12"
;;
2)
echo "Install Nginx 1.13"
;;
3)
echo "Install Nginx 1.14"
;;
4)
clear
mem_info_1
continue
esac
done
;;
2)
clear
mem_info_3
while true
do
read -p "请输入要安装的版本:" mem_2
case $mem_2 in
1)
echo "Install PHP 1.12"
;;
2)
echo "Install PHP 1.13"
;;
3)
echo "Install PHP 1.14"
;;
4)
clear
mem_info_1
continue
esac
done
;;
3)
clear
mem_info_4
while true
do
read -p "请输入要安装的版本:" mem_2
case $mem_2 in
1)
echo "Install Mysql 1.12"
;;
2)
echo "Install Mysql 1.13"
;;
3)
echo "Install Mysql 1.14"
;;
4)
clear
mem_info_1
continue
esac
done
;;
4)
clear
mem_info_1
break
esac
done
6.shell 数组
1.什么是数组
数组其实也是变量的意思,传统的变量只能存储一个值,但属组可以存储多个值
2.数组的分类
shell数组分为普通数组和关联数组
普通数组:只能使用整数作为数组索引
关联数组:可以使用字符串作为数组索引
books=(linux nginx shell) 普通数组 python(列表)
------------------------
|linux | nginx | shell |
------------------------
| 0 | 1 | 2 | 索引(下标)
ps :普通数组下标只能是整数
[root@manage functions]# book=(linux nginx shell)
[root@manage functions]# echo $book
linux
[root@manage functions]# echo ${book[3]}
[root@manage functions]# echo ${book[2]}
shell
[root@manage functions]# echo ${book[1]}
nginx
info=([name]=abc [age]=18 [skill]=linux) 关联数组 python(字典)
----------------------
| abc | 18 | linux |
| name | age | skill | 索引(下标)
----------------------
PS:关联数组的下标可以是字符串
#需要先声明
[root@manage functions]# declare -A init
[root@manage functions]# init=([name]=abc [age]=18 [skill]=linux)
[root@manage functions]# echo ${init[name]}
abc
[root@manage functions]# echo ${init[age]}
18
[root@manage functions]# echo ${init[skill]}
linux
[root@manage functions]# echo ${init[*]}
abc 18 linux
#还可以取出索引
[root@manage functions]# echo ${!init[@]}
name age skill
3.普通数组仅能使用整数来作为索引
1.普通数组的赋值
#方式1:针对每个索引进行赋值(数组名[索引]=变量值)
[root@manage functions]# array1[0]=pear
[root@manage functions]# array1[1]=apple
[root@manage functions]# array1[2]=orange
[root@manage functions]# echo ${array1[1]}
apple
[root@manage functions]# echo ${array1[0]}
pear
[root@manage functions]# echo ${array1[2]}
orange
#方式2:一次赋多个值(数组名=(多个变量值))
[root@manage functions]# array2=(tom jack ali)
[root@manage functions]# array3=(tom jack ali "bash shell")
[root@manage functions]# array4=(1 2 3 "bash shell" [20]=docker)
[root@manage functions]# echo ${array2[0]}
tom
[root@manage functions]# echo ${array2[2]}
ali
[root@manage functions]# echo ${array3[2]}
ali
[root@manage functions]# echo ${array3[3]}
bash shell
[root@manage functions]# echo ${array4[5]}
[root@manage functions]# echo ${array4[4]}
[root@manage functions]# echo ${array4[3]}
bash shell
[root@manage functions]# echo ${array4[20]}
docker
7.数组的遍历与循环
1.数组的遍历与循环是啥?
其实就是使用对数组进行批量赋值,然后通过循环方式批量取出数组的值对其进行统计
2.如果需要统计一个文件中某个字段出现的次数,怎么办?
思路就是:要统计谁就将谁作为数组的索引,注意仅支持关联数组。
3.如上的方式可以实现数组的赋值,但数组赋值后还需要遍历结果,才能完成统计需求,遍历的方式有以下2种
1. 通过数组的个数进行遍历(不推荐)
2. 通过数组的索引进行遍历(推荐)
1.普通数组赋值与遍历示例
[root@manage array]# cat array01.sh
#!/bin/bash
while read line
do
host[i++]=$line
done </etc/hosts
for item in ${!host[@]}
do
echo "你的索引是:$item 你对应的值是:${host[$item]}"
done
[root@manage array]# sh array01.sh
你的索引是:0 你对应的值是:127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
你的索引是:1 你对应的值是:::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
[root@manage array]# cat array02.sh
#!/bin/bash
declare -A login
while read line
do
types=$(echo $line |awk -F ":" '{print $NF}')
let login[$types]++
done</etc/passwd
for item in ${!login[@]}
do
echo "你的索引是:$item 索引出现的次数是:${login[$item]}"
done
[root@manage array]# sh array02.sh
你的索引是:/sbin/nologin 索引出现的次数是:21
你的索引是:/bin/sync 索引出现的次数是:1
你的索引是:/bin/bash 索引出现的次数是:35
你的索引是:/sbin/shutdown 索引出现的次数是:1
你的索引是:/sbin/halt 索引出现的次数是:1
[root@manage array]# cat sex.txt
jack m
alice f
tom m
rose f
robin m
abc m
ttt f
[root@manage array]# cat array03.sh
#!/bin/bash
declare -A sex
while read line
do
#1.取出文件的行,将我们需要统计的列给提取出来
types=$(echo $line |awk '{print $2}')
#2.要统计什么,就将谁作为索引名称:sex[索引]=值
let sex[$types]++
done<sex.txt
#3.遍历索引
for item in ${!sex[@]}
do
echo "你的索引是:$item 该索引出现的次数是:${sex[$item]}"
done
需求1:使用shell数组统计 nginx的访问日志,统计TOP10的IP
需求2:使用shell数组统计 nginx的访问日志,统计TOP10的URI
[root@manage array]# cat array04.sh
#!/bin/bash
declare -A sex
while read line
do
#1.取出文件的行,将我们需要统计的列给提取出来
types=$(echo $line |awk '{print $1}')
#2.要统计什么,就将谁作为索引名称:sex[索引]=值
let sex[$types]++
done<access.log
#3.遍历索引
for item in ${!sex[@]}
do
echo "${sex[$item]} $item"
done
#用awk数组取值
awk '{array[$1]++} END { for (key in array) print array[key],key }' access.log | sort -rn |head