Shell阶段04 shell流程case语句, 服务启动停止脚本(rsync, nginx), shell加锁机制, case示例(系统管理工具箱,Jumpserver,多级菜单), 信号捕捉trap, 创建临时文件mktemp
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
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
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 ]
#加锁机制 当这个脚本被某一个人执行的时候,别人是无法执行的,只能等待执行结束之后,才能执行 #优化脚本(通过创建文件,判断文件是否存在来实现锁的功能) ----------------------------------------------- [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 正在运行中,请稍后再执行......
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
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