Shell阶段04 shell流程case语句, 服务启动停止脚本(rsync, nginx), shell加锁机制, case示例(系统管理工具箱,Jumpserver,多级菜单), 信号捕捉trap, 创建临时文件mktemp

1.流程控制语句之case语句

case主要作用是对程序的选择,循环等操作

#语法:

case 变量 in
    变量值1)
        命令序列
        ;;    #命令序列结束符
    变量值2)
        命令序列
        ;;
    变量值3|变量值4) #符合变量值3或者4都可以
        命令序列
        ;;
    变量值N)
        命令序列
        ;;
    *)            #不符合上面所有条件
        命令序列
        exit    #或者其他命令 (最后的命令不用加;;)
esac

#语法示例
安装不同PHP的版本
    1. 菜单, PHP版本的菜单
    2. 提示用户根据菜单进行选择安装不同的PHP版本
    3. 根据用户选择进行安装不同的PHP版本

[root@shell01 scripts]# vim case-1.sh
#!/bin/bash
#1.准备PHP的版本菜单
cat<<EOF
##########################
1.安装PHP-5.5版本
2.安装PHP-5.6版本
3.安装PHP-7.1版本
4.退出当前安装
##########################
EOF
#2.提示用户根据菜单进行选择安装不同的PHP版本
read -p "请根据上方菜单进行选择安装不同的PHP版本[1|2|3|4]: " Install
#3.根据用户的选择,进行安装不同的版本
case $Install in
    1)
        echo "你闲着了安装PHP-5.5版本........."
        echo "正在安装PHP-5.5版本,请稍后......"
        sleep 3    #等待3秒
        echo "PHP-5.5版本安装成功............."
        ;;
    2)
        echo "你闲着了安装PHP-5.6版本........."
        echo "正在安装PHP-5.6版本,请稍后......"
        sleep 3    #等待3秒
        echo "PHP-5.6版本安装成功............."
        ;;
    3)
        echo "你闲着了安装PHP-7.1版本........."
        echo "正在安装PHP-7.1版本,请稍后......"
        sleep 3    #等待3秒
        echo "PHP-7.1版本安装成功............."
        ;;
    4)
        echo "你没有选择安装任何PHP版本! 程序退出!"
        exit
        ;;
    *)
        echo "你的选择不符合要求!请根据上方菜单进行选择[1|2|3|4]."
        exit
esac

 

2.case语句之场景示例(rsync)

服务启动停止脚本

1.编写一个rsync的启动停止脚本
    实现:    start    stop    status    restart
    1.如何启动rsync
    /usr/bin/rsync --daemon
    2.如何停止rsync
    pkill rsync        #注意: 千万不要使用rsync作为脚本的名字
    3.根据什么来判断服务的状态  pid文件 (可以不通过pid,通过状态,后台进程去判断,但比较麻烦,不如pid判断简单)
参考系统中其他服务的pid文件,如果系统不自动生成pid文件我们自己创建 #(这里不是用system管理,无法用system status去查看)
   系统自动生成的pid文件里是该进程的pid号
[root@shell01 scripts]# vim case-2.sh #!/bin/bash #1.引用函数库 [ -f /etc/init.d/functions ] && source /etc/init.d/functions || echo "函数库文件不存在!" #2.判断位置变量的个数是否只有一个 if [ $# -ne 1 ];then echo "Usage: $0 {start|stop|status|restart}" exit fi #3.编写case语句选项 Pid_File=/var/run/rsync.pid #这里启动不会自动创建pid文件,需要脚本自行创建 case $1 in start) if [ -f $Pid_File ];then action "服务Rsync正在运行中......" /bin/true exit else #当服务要启动的时候,需要手动创建pid文件 touch $Pid_File && /usr/bin/rsync --daemon &>/dev/null && sleep 3 #给3秒启动时间 if [ $? -eq 0 ];then action "服务Rsync启动成功....." /bin/true else action "服务Rsync启动失败....." /bin/false fi fi ;; stop) if [ -f $Pid_File ];then #当服务在启动的状态下,pid文件是存在的,如果需要停止服务,同样需要把pid文件删除 rm -f $Pid_File && pkill rsync && sleep 2 if [ $? -eq 0 ];then action "服务Rsync停止成功......" /bin/true else action "服务Rsync停止失败......" /bin/false fi else action "服务Rsync不在运行中......" /bin/true exit fi ;; status) #当pid文件存在时,则服务在运行中,pid文件不存在时,服务不在运行中 if [ -f $Pid_File ];then action "服务Rsync正在运行中......" /bin/true else action "服务Rsync不在运行中......" /bin/true fi ;; restart) #重启,当服务正在运行中,需要停止服务再启动服务,当服务不在运行中,需要直接启动 if [ -f $Pid_File ];then #停止服务 rm -f $Pid_File && pkill rsync && sleep 2 if [ $? -eq 0 ];then action "服务Rsync停止成功......" /bin/true else action "服务Rsync停止失败......" /bin/false fi #启动服务 touch $Pid_File && /usr/bin/rsync --daemon &>/dev/null && sleep 3 if [ $? -eq 0 ];then action "服务Rsync启动成功....." /bin/true else action "服务Rsync启动失败....." /bin/false fi action "服务Rsync重启成功...." /bin/true else action "服务Rsync不在运行中......" /bin/true #启动服务 touch $Pid_File && /usr/bin/rsync --daemon &>/dev/null && sleep 3 if [ $? -eq 0 ];then action "服务Rsync启动成功....." /bin/true else action "服务Rsync启动失败....." /bin/false fi action "服务Rsync重启成功...." /bin/true fi ;; *) echo "Usage: $0 {start|stop|status|restart}" exit esac

 

3.Nginx的启动停止脚本

start    stop    status      restart        reload

1.怎么启动Nginx
/usr/sbin/nginx #nginx启动时,pid文件系统会自动创建
2.怎么停止Nginx
/usr/sbin/nginx -s stop
3.怎么进行重启Nginx
先stop 再start
4.怎么进行平滑重启Nginx
/usr/sbin/nginx -s reload
5.在什么情况下,才能进行平滑重启
    只有在Nginx服务在运行的时候,才能进行平滑重启。如果Nginx服务没有在运行中,是不能进行平滑重启的。
-----------------------------------
[root@shell01 scripts]# vim case-3.sh
#!/bin/bash
#1.引用函数库
[ -f /etc/init.d/functions ] && source /etc/init.d/functions || echo "函数库文件不存在!"
#2.判断位置变量是否存在且只有一个
if [ $# -ne 1 ];then
    echo "Usage: $0 {start|stop|status|restart|reload}"
    exit
fi
#3.编写case语句
Pid_File=/var/run/nginx.pid
case $1 in
    start)
        if [ -f $Pid_File ];then
            action "Nginx服务正在运行中......." /bin/true
        else
            /usr/sbin/nginx &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务启动成功......" /bin/true
            else
                action "Nginx服务启动失败......" /bin/false
            fi
        fi
        ;;
    stop)
        if [ -f $Pid_File ];then
            /usr/sbin/nginx -s stop &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务停止成功......" /bin/true
            else
                action "Nginx服务停止失败......" /bin/false
            fi
        else
            action "Nginx服务不在运行中......" /bin/true
        fi
        ;;
    status)
        if [ -f $Pid_File ];then
            action "Nginx服务正在运行中......" /bin/true
        else
            action "Nginx服务不在运行中......" /bin/true
        fi
        ;;
    restart)
        if [ -f $Pid_File ];then
            #先停止服务
            /usr/sbin/nginx -s stop &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务停止成功...." /bin/true
            else
                action "Nginx服务停止失败...." /bin/false
            fi
            #启动服务
            /usr/sbin/nginx &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务启动成功......" /bin/true
                action "Nginx服务重启成功......" /bin/true
            else
                action "Nginx服务启动失败......" /bin/false
            fi
        else
            action "Nginx服务不在运行中....." /bin/false
            #启动服务
            /usr/sbin/nginx &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务启动成功......" /bin/true
                action "Nginx服务重启成功......" /bin/true
            else
                action "Nginx服务启动失败......" /bin/false
            fi
        fi
        ;;
    reload)
        if [ -f $Pid_File ];then
            /usr/sbin/nginx -s reload &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务平滑重启成功......" /bin/true
            else
                action "Nginx服务平滑重启失败......" /bin/false
            fi
        else
            action "Nginx服务没有在运行中,无法进行平滑重启...." /bin/false
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|status|restart|reload}"
        exit
esac
-----------------------------------------

#测试 [root@shell01 scripts]
# sh case-3.sh Usage: case-3.sh {start|stop|status|restart|reload} [root@shell01 scripts]# sh case-3.sh start Nginx服务正在运行中....... [ OK ] [root@shell01 scripts]# sh case-3.sh stop Nginx服务停止成功...... [ OK ]

 

4.加锁机制

#加锁机制
当这个脚本被某一个人执行的时候,别人是无法执行的,只能等待执行结束之后,才能执行
#优化脚本(通过创建文件,判断文件是否存在来实现锁的功能)
-----------------------------------------------
[root@shell01 scripts]# vim case-3.sh
#!/bin/bash
#1.引用函数库
[ -f /etc/init.d/functions ] && source /etc/init.d/functions || echo "函数库文件不存在!"
#2.判断位置变量是否存在且只有一个
if [ $# -ne 1 ];then
    echo "Usage: $0 {start|stop|status|restart|reload}"
    exit
fi
#2.5 进行加锁机制
Suo_File=/tmp/nginx.lock
if [ -f $Suo_File ];then
    echo "此脚本$0 正在运行中,请稍后再执行......"
    exit
fi
#2.6 加锁
touch $Suo_File &>/dev/null
#3.编写case语句
Pid_File=/var/run/nginx.pid
case $1 in
    start)
        if [ -f $Pid_File ];then
            action "Nginx服务正在运行中......." /bin/true
        else
            /usr/sbin/nginx &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务启动成功......" /bin/true
            else
                action "Nginx服务启动失败......" /bin/false
            fi
        fi
        ;;
    stop)
        if [ -f $Pid_File ];then
            /usr/sbin/nginx -s stop &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务停止成功......" /bin/true
            else
                action "Nginx服务停止失败......" /bin/false
            fi
        else
            action "Nginx服务不在运行中......" /bin/true
        fi
        ;;
    status)
        if [ -f $Pid_File ];then
            action "Nginx服务正在运行中......" /bin/true
        else
            action "Nginx服务不在运行中......" /bin/true
        fi
        ;;
    restart)
        if [ -f $Pid_File ];then
            #先停止服务
            /usr/sbin/nginx -s stop &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务停止成功...." /bin/true
            else
                action "Nginx服务停止失败...." /bin/false
            fi
            #启动服务
            /usr/sbin/nginx &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务启动成功......" /bin/true
                action "Nginx服务重启成功......" /bin/true
            else
                action "Nginx服务启动失败......" /bin/false
            fi
        else
            action "Nginx服务不在运行中....." /bin/false
            #启动服务
            /usr/sbin/nginx &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务启动成功......" /bin/true
                action "Nginx服务重启成功......" /bin/true
            else
                action "Nginx服务启动失败......" /bin/false
            fi
        fi
        ;;
    reload)
        if [ -f $Pid_File ];then
            /usr/sbin/nginx -s reload &>/dev/null && sleep 2
            if [ $? -eq 0 ];then
                action "Nginx服务平滑重启成功......" /bin/true
            else
                action "Nginx服务平滑重启失败......" /bin/false
            fi
        else
            action "Nginx服务没有在运行中,无法进行平滑重启...." /bin/false
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|status|restart|reload}"
        # 这里删掉exit
esac
#4.解锁(上方不要出现exit)
rm -f $Suo_File &>/dev/null
----------------------------------------

#测试
[root@shell01 scripts]# sh case-3.sh stop
Nginx服务停止成功......                                    [  OK  ]
#在另一个窗口同时执行脚本
[root@shell01 scripts]# sh case-3.sh stop
此脚本case-3.sh 正在运行中,请稍后再执行......

 

case语句场景示例

1. 实现系统管理工具箱

#####################
1.显示磁盘的使用情况
2.显示内存使用情况
3.显示系统负载情况
4.显示CPU使用情况
5.查看系统Eth0网卡
6.查看系统外网IP
7.查看系统版本
8.查看系统内核版本
9.退出脚本程序
0.显示帮助菜单
#####################

循环语句
while true
do
...
done
-------------------------------------
[root@shell01 scripts]# vim toolbox.sh
#!/bin/bash
#进行无限循环
while true
do
#1.编写菜单
cat<<EOF
#####################
1.显示磁盘的使用情况
2.显示内存使用情况
3.显示系统负载情况
4.显示CPU使用情况
5.查看系统Eth0网卡
6.查看系统外网IP
7.查看系统版本
8.查看系统内核版本
9.退出脚本程序
0.显示帮助菜单
#####################
EOF
#2.提示用户输入要查看的信息
read -p "请根据上方菜单进行选择要查看的信息: " Num
#3.根据用户输入的数字进行编写case语句
case $Num in
    1)
        echo "系统磁盘使用情况如下:"
        df -h
        ;;
    2)
        echo "系统内存使用情况如下:"
        free -m
        ;;
    3)
        echo "系统负载情况如下:"
        uptime
        ;;
    4)
        echo "系统CPU使用情况如下:"
        htop
        ;;
    5)
        echo "系统Eth0网卡IP地址如下:"
        ifconfig eth0 | awk 'NR==2{print $2}'
        ;;
    6)
        echo "系统外网IP如下:"
        curl -s ifconfig.me
        echo    #上面命令不会换行,这里换下行
        ;;
    7)
        echo "系统版本版本如下:"
        awk '{print $1,$4}' /etc/redhat-release
        ;;
    8)
        echo "系统内核版本如下:"
        uname -r
        ;;
    9)
        echo "脚本程序退出!"
        exit
        ;;
    0)
        echo "菜单!"
        ;;
    *)
        echo "你输入的不正确,请根据上方菜单进行选择!"
esac
done

实现简单的Jumpserver

1.执行脚本后,显示菜单,菜单内容所有可管理的主机
2.选择菜单的一个选项,连接对应的主机
3.需要进行死循环,连接成功一个主机之后,退出还能继续连接其他的主机
4.不能让其实用Ctrl c d z 等操作
5.退出当前脚本的会话,再次登录时,还是自动的执行该脚本,不能操作后台的操作
/etc/bashrc   /etc/profile
6.留一个出口,不让别人知道

菜单
#####################
1.管理Web01-10.0.0.7
2.管理Lb01-10.0.0.5
3.管理Db01-10.0.0.51
4.显示主机列表
#####################

[root@shell01 scripts]# vim jumpserver.sh
#!/bin/bash
#1.定义函数菜单
menu() {
cat<<EOF
#####################
1.管理Web01-10.0.0.7
2.管理Lb01-10.0.0.5
3.管理Db01-10.0.0.51
4.显示主机列表
#####################
EOF
}
#3.禁止输入Ctrl+c、d、z等操作
trap "" HUP INT TSTP    #捕捉信号,不进行处理
#4.进行循环操作
while true
do
    #2.打印菜单
    menu
    #5.提示用户输入对应的编号
    read -p "请根据上方菜单的主机列表,进行选择要连接的主机[1|2|3|4]: " Num
    #6.根据选择进行编写case语句
    case $Num in
        1)
            clear
            #7.测试对应的主机IP是否能通
            ping -c1 -W1 10.0.0.7 &>/dev/null
            if [ $? -eq 0 ];then
                echo "正在连接Web01-10.0.0.7主机......"
                ssh root@10.0.0.7
            else
                echo "Web01的主机网络不可达!无法进行远程连接!"
            fi
            ;;
        2)
            clear
            #7.测试对应的主机IP是否能通
            ping -c1 -W1 10.0.0.5 &>/dev/null
            if [ $? -eq 0 ];then
                echo "正在连接Lb01-10.0.0.5主机......"
                ssh root@10.0.0.5
            else
                echo "Lb01的主机网络不可达!无法进行远程连接!"
            fi
            ;;
        3)
            clear
            #7.测试对应的主机IP是否能通
            ping -c1 -W1 10.0.0.51 &>/dev/null
            if [ $? -eq 0 ];then
                echo "正在连接Db01-10.0.0.51主机......"
                ssh root@10.0.0.51
            else
                echo "Db01的主机网络不可达!无法进行远程连接!"
            fi
            ;;
        4)
            clear    #清屏
            ;;
        anhao)
            echo "内部人员才能执行的操作!退出程序!进入后台管理!"
            exit
            ;;
        *)
            echo "你输入的不符合要求!请根据菜单进行选择要连接的主机!"
            clear
    esac
done
-----------------------------------
#5.每次登陆自动的执行该脚本,不能操作后台的操作(在bashrc里追加执行命令)
[root@shell01 scripts]# vim /etc/bashrc
...
/bin/sh /scripts/jumpserver.sh

实现一个多级菜单

1.主菜单,两个辅菜单
安装Nginx和PHP

########主菜单#######
1.安装Nginx服务
2.安装PHP服务
3.退出脚本
#####################

子菜单
########子菜单#######
1.安装Nginx-1.16版本
2.安装Nginx-1.17版本
3.返回上一级菜单
#####################

子菜单
########子菜单#######
1.安装PHP-5.6版本
2.安装PHP-7.1版本
3.返回上一级菜单
#####################

----------------------------------------
[root@shell01 scripts]# vim case-2.sh
#!/bin/bash
#1.定义菜单
menu() {
cat<<EOF
########主菜单#######
1.安装Nginx服务
2.安装PHP服务
3.退出脚本
#####################
EOF
}
Nginx_menu() {
cat<<EOF
########子菜单#######
1.安装Nginx-1.16版本
2.安装Nginx-1.17版本
3.返回上一级菜单
#####################
EOF
}
Php_menu() {
cat<<EOF
########子菜单#######
1.安装PHP-5.6版本
2.安装PHP-7.1版本
3.返回上一级菜单
#####################
EOF
}
#2.进入循环
while true
do
    #3.显示主菜单,提示用户根据菜单进行选择安装不同的服务
    menu
    read -p "请根据主菜单进行选择安装不同的服务: " Install
    case $Install in
        1)
            clear
            echo "你选择安装Nginx服务...."
            while true
            do
                Nginx_menu
                read -p "请根据上方Nginx菜单进行选择安装不同的Nginx版本: " Nginx_Install
                case $Nginx_Install in
                    1)
                        clear
                        echo "你选择了安装Nginx-1.16版本"
                        echo "正在安装Nginx-1.16版本"
                        sleep 2
                        echo "安装Nginx-1.16版本成功"
                        ;;
                    2)
                        clear
                        echo "你选择了安装Nginx-1.17版本"
                        echo "正在安装Nginx-1.17版本"
                        sleep 2
                        echo "安装Nginx-1.17版本成功"
                        ;;
                    3)
                        clear
                        break #跳出当前循环,继续执行循环外面的命令
                        ;;
                    *)
                        clear
                        echo "你输入的不符合要求!"
                esac
            done
            ;;
        2)
            clear
            echo "你选择安装PHP服务..."
            while ture
            do
                Php_menu
                read -p "请根据上方PHP菜单进行选择安装不同的PHP版本: " PHP_Install
                case $PHP_Install in
                    1)
                        clear
                        echo "你选择了安装PHP-5.6版本"
                        echo "正在安装PHP-5.6版本版本"
                        sleep 2
                        echo "安装PHP-5.6版本成功"
                        ;;
                    2)
                        clear
                        echo "你选择了安装PHP-7.1版本"
                        echo "正在安装PHP-7.1版本版本"
                        sleep 2
                        echo "安装PHP-7.1版本成功"
                        ;;
                    3)
                        clear
                        break #跳出当前循环,继续执行循环外面的命令
                        ;;
                    *)
                        clear
                        echo "你输入的不符合要求!"
                esac
            done
            ;;
        3)
            clear
            echo "你选择了退出脚本!"
            exit
            ;;
        *)
            clear
            echo "你输入的不符合要求!"
    esac
done

 

信号捕捉trap 

trap 命令可以捕捉信号,修改信号原来的功能,实现自定义功能

在脚本或程序的执行过程中,我们可以通过发送信号的方式,打断或终止程序的执行过程,为了避免这 种情况,我们可以使用信号捕捉,来自定义信号处理。

trap [-lp] [[arg] signal_spec ...]

#常用选项
-l #显示所有信号
-p #显示所有自定义的信号

trap 'command' signal #自定义指定信号的处理方式
trap '' signal #忽略指定的信号
trap '-' signal #恢复信号默认操作
trap func EXIT #退出时执行func

#查看所有信号:
[root@ubuntu2204 ~]# trap -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
......
......


#信号3种表示表示,可以写如下3中(大小写都支持)
trap 'command' SIGQUIT #全名
trap 'command' 3 #信号代号
trap 'command' QUIT #名称后半部分

例:
[root@ubuntu2204 ~]# cat trap.sh
#!/bin/bash
trap "echo '捕捉到了 ctrl+c信号'" SIGINT
trap "echo '捕捉到了 ctrl+\信号'" quit
trap -p
for i in {1..15};do
    sleep 1
    echo $i
done

trap '' int
trap -p
for i in {16..30};do
    sleep 1
    echo $i
done

trap '-' int
trap -p
for i in {31..45};do
    sleep 1
    echo $i
done

 

创建临时文件mktemp

mktemp [OPTION]... [TEMPLATE]

#常用选项
-d|--directory     #创建目录
-u|--dry-run       #只输出命令,不执行
-p DIR|--tmpdir[=DIR]   #指明临时文件所存放目录位置
-t                 #将文件保存到$TMPDIR 定义的目录中,如果该
变量未定义,则保存到/tmp 目录中


#X表示随机多少位名称
[root@ubuntu2204 ~]# mktemp XXXX
UYtW
[root@ubuntu2204 ~]# mktemp testXXX
test19C

[root@ubuntu2204 ~]# mktemp
/tmp/tmp.YQXxc3bHdI

#创建并赋值给变量
[root@ubuntu2204 ~]# tmp=`mktemp`
[root@ubuntu2204 ~]# echo $tmp
/tmp/tmp.wQAdrqn1UR

#创建目录
[root@ubuntu2204 ~]# mktemp -d
/tmp/tmp.2iLac1ruHt
[root@ubuntu2204 ~]# ll /tmp/tmp.2iLac1ruHt/
total 0

#假删除
[root@ubuntu2204 ~]# cat trash.sh
#!/bin/bash
DIR=`mktemp -d /tmp/trash-$(date +%F_%H-%M-%S)XXXXXX`
mv $* $DIR
echo $* is move to $DIR

 

posted @ 2024-05-21 17:53  战斗小人  阅读(38)  评论(0编辑  收藏  举报