目录
一、循环语句 until
1.1 until 介绍
1.2 until 语法
1.3 案例
1.4 总结
二、shell 函数
2.1 函数介绍
2.2 函数定义
2.3 函数调用
三、条件循环语句 case
3.1 case 介绍
3.2 case 语法
3.4 案例
四、综合案例
系统中还有一个类似while的循环语句,大家可以看看until语句,不同于while的是,当条件为假时开始until循环。
特点:条件为假就进入循环;条件为真就退出循环
until expression [ 1 -eq 1 ] (( 1 >= 1 ))
do
command
command
...
done
使用while循环和until循环打印数字接龙,要求while循环输出1-5,until循环输出6-9.
#!/bin/bash
#Description: 数字接龙
i=1
while [ $i -le 5 ]
do
echo $i
let i++
until [ $i -le 5 ]
do
echo $i
let i++
[ $i -eq 10 ]&&break
done
done
shell 脚本中的代码是按照执行的优先级的顺序从上往下抒写的,代码量越大,在脚本调试的时候就越难排错,当因执行需要调整代码执行顺序的时候就需要不断的复制粘贴,或者删除部分代码来完成,这和从写一个脚本花费的时候相比甚至需要更长的时间。
代码量大后遇到的问题:
单个脚本代码量大 (300-500行)
阅读修改耗时费力
排错困难
改变执行顺序困难
为了解决这些问题,我们可以把代码模块化,按需调用。
shell 中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数。给这段代码起个名字称为函数名,后续可以直接调用该段代码的功能。
将完成一个功能的一段代码进行命名、封装。
函数的优点:
# 语法一:
函数名 () {
代码块
return N
}
# 语法二:
function 函数名 {
代码块
return N
}
# 函数中 return 说明:
1.return 可以结束一个函数,类似于前面讲的循环控制语句break(结束当前循环,执行循环体后面的代码)
2.return 默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间。
3.如果没有 return 命令,函数将返回最后一个 Shell 的退出值。
函数定义案例演示
[root@shell ~]# vim fun-1.sh
#!/bin/bash
fun1 () {
echo "first function"
echo "haha"
return 0
}
function fun2 {
echo "second function"
echo "xixi"
return 110
}
[root@shell ~]# vim fun-2.sh
#!/bin/bash
hello(){
echo "hello sky $1"
hostname
}
menu(){
cat <<-EOF
1. mysql
2. web
3. app
4. exit
EOF
}
[root@shell ~]# source fun-2.sh
[root@shell ~]# . fun-2.sh
[root@shell ~]# hello 99
hello sky 99
shell
[root@shell ~]# menu
1. mysql
2. web
3. app
4. exit
[root@shell ~]# vim ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
hello(){
echo "hello sky $1"
hostname
}
menu(){
cat <<-EOF
1. mysql
2. web
3. app
4. exit
EOF
}
# 注意:当用户打开 bash 的时候会读取该文件
[root@shell ~]# vim fun-1.sh
#!/bin/bash
fun1 () {
echo "first function"
echo "haha"
return 0
}
function fun2 {
echo "second function"
echo "xixi"
return 110
}
# 调用函数(函数名)
fun2;fun1
[root@shell ~]# sh fun-1.sh
second function
xixi
first function
haha
在生产环境中,我们总会遇到一个问题需要根据不同的状况来执行不同的预案,那么我们要处理这样的问题就要首先根据可能出现的情况写出对应预案,根据出现的情况来加载不同的预案。
特点:根据给予的不同条件执行不同的代码块。
# 比如你去相亲:你会在脑子里出现以下的预案:
第一眼看到对方父亲,你应该说:伯父好
第一眼看到对方母亲,你应该说:伯母好
第一眼看到对方奶奶,你应该说:奶奶好
。。。。
# 而这个例子中触发就是你第一眼看到了对方的谁,预案则是叫什么称呼。
# 再来说一个计算机的相关例子---监控内存使用率:
内存使用率低于80%, 脚本输出: 绿色字体的Memory use xx%
内存使用率大于80%小于90%, 脚本输出: 黄色字体的Memory use xx%
内存使用大于90%, 脚本输出: 红色字体的Memory use xx%
case $var in # 定义变量; var 代表是变量名
pattern 1) # 模式1;用 | 符号分割多个(选项)模式,相当于or
command1 # 需要执行的语句
;; # 两个分号代表命令结束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) # default,不满足以上模式,默认执行*)下面的语句
command4
;;
esac # esac 表示 case 语句结束
[root@shell ~]# vim case.sh
#!/bin/bash
read -p "性别: " gender
case $gender in
B|b|男)
echo "显示,您好"
;;
G|g|女)
echo "女士,您好"
;;
*)
echo "请输入性别"
esac
[root@shell ~]# sh case.sh
性别: 男
先生,您好
[root@shell ~]# sh case.sh
性别: b
先生,您好
[root@shell ~]# sh case.sh
性别: G
女士,您好
案例需求
写一个nginx启动管理脚本,可以实现 /etc/init.d/nginx start|stop|restart|status|reload
或者 systemctl start nginx。注意:提前编译安装 nginx
#!/bin/bash
#variables
nginx_install_doc=/usr/local/nginx
proc=nginx
nginxd=$nginx_install_doc/sbin/nginx
pid_file=$nginx_install_doc/logs/nginx.pid
# Source function library.
if [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
else
echo "not found file /etc/init.d/functions"
exit
fi
# 假如pid文件存在,那么统计一下 nginx 进程数量
if [ -f $pid_file ];then
nginx_process_id=`cat $pid_file`
nginx_process_num=`ps aux |grep $nginx_process_id|grep -v "grep"|wc -l`
fi
#function
start () {
# 如果nginx 没有启动直接启动,否则报错 已经启动
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
echo "nginx running..."
else
# 如果pid文件存在,但是没有进程,说明上一次非法关闭了nginx,造成pid文件没有自动删除,所以启动nginx之前先删除旧的pid文件
if [ -f $pid_file ] && [ $nginx_process_num -lt 1 ];then
rm -f $pig_file
# 可以使用两个函数,两种方法来执行命令,并返回执行结果
#1)daemon
#2)action 建议这个,简单易用
#echo " nginx start `daemon $nginxd` "
action "nginx start" $nginxd
fi
#echo " nginx start `daemon $nginxd` "
action "nginx start" $nginxd
fi
}
stop () {
# 判断nginx启动的情况下才会执行关闭,如果没启动直接报错,或者提示用户服务没启动,这里我直接报错的原因是为了给大家演示失败的输出
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
action "nginx stop" killall -s QUIT $proc
rm -f $pid_file
else
action "nginx stop" killall -s QUIT $proc 2>/dev/null
fi
}
restart () {
stop
sleep 1
start
}
reload () {
# 重载的目的是让主进程重新加载配置文件,但是前提是服务必须开启
# 这里先判断服务是否开启,开启就执行加载,没有开启直接报加载错误
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
action "nginx reload" killall -s HUP $proc
else
action "nginx reload" killall -s HUP $proc 2>/dev/null
fi
}
status () {
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
echo "nginx running..."
else
echo "nginx stop"
fi
}
#callable
case $1 in
start) start;;
stop) stop;;
restart) restart;;
reload) reload;;
status) status;;
*) echo "USAGE: $0 start|stop|restart|reload|status";;
esac
上一篇文章:【Shell 脚本速成】10、Shell 流程控制 while 循环_Stars.Sky的博客-CSDN博客
参考文档:流程控制-case语句-组团学