1. 条件表达式

1.1 文件判断**

常用文件测试操作符 说明
-d文件,d的全拼为directory 文件存在且为目录则为真,即测试表达式成立
-f文件,f的全拼为file 文件存在且为普通文件则为真,即测试表达式成立
-e文件,e的全拼为exist 文件存在则为真,即测试表达式成立。注意区别于“-f”,-e不辨别是目录还是文件
-r文件,r的全拼为read 文件存在且可读则为真,即测试表达式成立
-s文件,s的全拼为size 文件存在且文件大小不为0则为真,即测试表达式成立
-w文件,w的全拼为write 文件存在且可写则为真,即测试表达式成立
-x文件,x的全拼为executable 文件存在且可执行则为真,即测试表达式成立
-L文件,L的全拼为link 文件存在且为链接文件则为真,即测试表达式成立
fl -nt f2,nt 的全拼为 newer than 文件fl比文件f2新则为真,即测试表达式成立。根据文件的修改时间来计算
fl -ot f2,ot 的全拼为 older than 文件fl比文件f2旧则为真,即测试表达式成立。根据文件的修改时间来计算

判断文件是否存在

  1. [root@clsn scripts]# [ -f /etc/hosts ]
  2. [root@clsn scripts]# echo $?
  3. 0
  4. [root@clsn scripts]# [ -f /etc/hosts1 ]
  5. [root@clsn scripts]# echo $?
  6. 1

判断文件是否存在,返回方式

  1. [root@clsn scripts]# [ -f /etc/hosts ] && echo "文件存在" || echo "文件不存在"
  2. 文件存在
  3. [root@clsn scripts]# [ -f /etc/hosts1 ] && echo "文件存在" || echo "文件不存在"
  4. 文件不存在

判断目录是否存在

  1. [root@clsn scripts]# [ -d /tmp ] && echo "目录存在" || echo "目录不存在"
  2. 目录存在
  3. [root@clsn scripts]# [ -d /tmp1 ] && echo "目录存在" || echo "目录不存在"
  4. 目录不存在

使用变量的方法进行判断

  1. dir=/etc1/;[ -d $dir ] && tar zcf etc.tar.gz $dir || echo "$dir目录不存在"

1.2 字符串判断

常用字符串测试操作符 说明
-n “字符串” 若字符串的长度不为0,则为真,即测试表达式成立,n可以理解为no zero
-Z “字符串” 若字符串的长度为0,则为真,即测试表达式成立,z可以理解为zero的缩写
“串 1”== “串 2” 若字符串1等于字符串2,则为真,即测试表达式成立,可使用”==”代替”=”
“串 1” != “串 2” 若字符串1不等于字符串2,则为真,即测试表达式成立,但不能用”!==”代替”!=”
1.对于字符串的测试,一定要将字符串加双引号之后再进行比较。
2.空格非空

-z 判断字符串长度

  1. [root@clsn scripts]# x= ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'
  2. 输入为空
  3. [root@clsn scripts]# x=12 ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'
  4. 输入有内容

-n 判断字符串长度

  1. [root@clsn scripts]# x=12 ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'
  2. 输入有内容
  3. [root@clsn scripts]# x= ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'
  4. 输入为空

“串 1” == “ 串 2 “ 使用定义变量的方式进行判断

  1. cmd=$1
  2. [ "$cmd" == "start" ] && echo start
  3. # 测试
  4. [root@clsn scripts]# cmd=start;[ "$cmd" == "start" ] && echo start
  5. start

1.3 整数判断

在[]以及test中
使用的比较符号
在(())和[[]]中
使用的比较符号
说明
-eq ==或= 相等,全拼为equal
-ne != 不相等,全拼为not equal
-gt > 大于,全拼为greater than
-ge >= 大于等于,全拼为greater equal
-lt < 小于,全拼为丨ess than
-le <= 小于等于,全拼为less equal

判断两数是否相等

  1. [root@clsn scripts]# [ 1 -eq 1 ]
  2. [root@clsn scripts]# echo $?
  3. 0
  4. [root@clsn scripts]# [ 1 -eq 2 ]
  5. [root@clsn scripts]# echo $?
  6. 1

大于等于

  1. [root@clsn ~]# [ 11 -ge 1 ] && echo "成立" || echo "不成立"
  2. 成立

小于

  1. [root@clsn ~]# [ 11 -lt 1 ] && echo "成立" || echo "不成立"
  2. 不成立

大于

  1. [root@clsn ~]# [ 11 -gt 1 ] && echo "成立" || echo "不成立"
  2. 成立

不等于

  1. [root@clsn ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"
  2. 成立

1.4 逻辑符号

在[]和test中使用的操作符 说明 在[[]]和中使用的操作符 说明
-a [ 条件A -a 条件B ]
A与B都要成立,整个表达式才成立
&& and,与,两端都为真,则结果为真
-o [ 条件A -o 条件B]
A与B都不成立,整个表达式才不成立
|| or,或,两端有一个为真,则结果为真
! not,非,两端相反,则结果为真

逻辑操作符与整数判断配合

  1. [root@clsn ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"
  2. 成立

取反

  1. [root@clsn ~]# [ ! 11 -ne 1 ] && echo "成立" || echo "不成立"
  2. 不成立

两边都为真

  1. [root@clsn ~]# [ 11 -ne 1 -a 1 -eq 1 ] && echo "成立" || echo "不成立"
  2. 成立

至少有一边为真

  1. [root@clsn ~]# [ 11 -ne 1 -o 1 -eq 1 ] && echo "成立" || echo "不成立"
  2. 成立

感叹号的特殊用法
使用历史命令,感叹号加上history中的序号,即可执行

  1. [root@clsn ~]# !516
  2. ls
  3. anaconda-ks.cfg bootime.avg setup.sh vim

1.5 【练习题】开发3个shell脚本比较2个整数大小

要求:
1. 分别以定义变量,脚本传参以及read读入的方式写3个脚本。
2. 用条件表达式(禁止if语句)进行判断。
3. 将2个整数的比较结果输出到屏幕,出错需要提示。
使用定义变量方法

  1. [root@clsn panduan1]# cat panduan1.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: panduan1.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 11:27:32
  9. # Description:
  10. #############################################################
  11. NUM1=6
  12. NUM2=2
  13. expr 1 + $NUM1 &>/dev/null
  14. [ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2
  15. expr 1 + $NUM2 &>/dev/null
  16. [ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2
  17. [ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2 && exit
  18. [ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit
  19. [ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

使用传参方法

  1. [root@clsn panduan1]# cat panduan_chuanchan.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: panduan1.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 11:27:32
  9. # Description:
  10. #############################################################
  11. [ $# -ne 2 ] && echo "UASGE $0 num1 num2 " && exit
  12. NUM1=$1
  13. NUM2=$2
  14. expr 1 + $NUM1 &>/dev/null
  15. [ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2
  16. expr 1 + $NUM2 &>/dev/null
  17. [ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2
  18. [ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2 && exit
  19. [ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit
  20. [ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

使用read读入

  1. [root@clsn panduan1]# cat panduan_read.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: panduan1.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 11:27:32
  9. # Description:
  10. #############################################################
  11. read -p "请输入第一个整数:" NUM1
  12. read -p "请输入第二个整数:" NUM2
  13. expr 1 + $NUM1 &>/dev/null
  14. [ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2
  15. expr 1 + $NUM2 &>/dev/null
  16. [ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2
  17. [ "$NUM1" -eq "$NUM2" ] && echo "$NUM1 = $NUM2" && exit
  18. [ "$NUM1" -gt "$NUM2" ] && echo "$NUM1 > $NUM2" && exit
  19. echo "$NUM1 < $NUM2"

2. if条件语句

条件表达式和if语句可以互相转换

2.1 三种语法

单分支语句

  1. if [ -f /etc/hosts ]
  2. then
  3. echo '文件存在'
  4. fi

双分支语句

  1. if [ -f /etc/hosts ]
  2. then
  3. echo "文件存在"
  4. else
  5. echo "文件不存在"
  6. echo "..." >>/tmp/test.log
  7. fi

多分支语句

  1. if [ -f /etc/hosts ]
  2. then
  3. echo " hosts文件存在"
  4. elif [ -f /etc/host ]
  5. then
  6. echo " host文件存在"
  7. fi

2.2 if条件语句小结

  单分支:一个条件一个结果
  双分支:一个条件两个结果
  多分支:多个条件多个结果

2.3 【练习题1】输入2个数字,比较大小(使用if语句结合条件表达式实现)

说明:
3个脚本:使用直接赋值,传参,read任一种方法写3种脚本(单分支,双分支,多分支)
示例脚本一:

  1. [root@clsn panduan1]# cat if_panduan_1.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: panduan1.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 11:27:32
  9. # Description:
  10. #############################################################
  11. read -p "请输入第一个整数:" NUM1
  12. expr 1 + $NUM1 &>/dev/null
  13. if [ $? -eq 2 ]
  14. then
  15. echo "$NUM1 不是整数 "
  16. exit 2
  17. fi
  18. read -p "请输入第二个整数:" NUM2
  19. expr 1 + $NUM2 &>/dev/null
  20. if [ $? -eq 2 ]
  21. then
  22. echo "$NUM2 不是整数 "
  23. exit 2
  24. fi
  25. # 判断输入数值大小
  26. if [ $NUM1 -eq $NUM2 ]
  27. then
  28. echo "$NUM1 = $NUM2"
  29. exit
  30. fi
  31. if [ $NUM1 -gt $NUM2 ]
  32. then
  33. echo "$NUM1 > $NUM2"
  34. exit
  35. fi
  36. if [ $NUM1 -lt $NUM2 ]
  37. then
  38. echo "$NUM1 < $NUM2"
  39. fi

示例脚本二:

  1. [root@clsn panduan1]# cat if_panduan_2.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: if_panduan_2.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 11:27:32
  9. # Description:
  10. #############################################################
  11. read -p "请输入第一个整数:" NUM1
  12. expr 1 + $NUM1 &>/dev/null
  13. if [ $? -eq 2 ]
  14. then
  15. echo "$NUM1 不是整数 "
  16. exit 2
  17. fi
  18. read -p "请输入第二个整数:" NUM2
  19. expr 1 + $NUM2 &>/dev/null
  20. if [ $? -eq 2 ]
  21. then
  22. echo "$NUM2 不是整数 "
  23. exit 2
  24. fi
  25. # 判断输入数值大小
  26. if [ $NUM1 -eq $NUM2 ]
  27. then
  28. echo "$NUM1 = $NUM2"
  29. exit
  30. else
  31. if [ $NUM1 -gt $NUM2 ]
  32. then
  33. echo "$NUM1 > $NUM2"
  34. exit
  35. else
  36. if [ $NUM1 -lt $NUM2 ]
  37. then
  38. echo "$NUM1 < $NUM2"
  39. fi
  40. fi
  41. fi

示例脚本三:

  1. [root@clsn panduan1]# cat if_panduan_3.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: if_panduan_3.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 11:27:32
  9. # Description:
  10. #############################################################
  11. read -p "请输入第一个整数:" NUM1
  12. expr 1 + $NUM1 &>/dev/null
  13. NUM1_FH=$?
  14. if [ $NUM1_FH -eq 2 ]
  15. then
  16. echo "$NUM1 不是整数 "
  17. exit 2
  18. else
  19. read -p "请输入第二个整数:" NUM2
  20. expr 1 + $NUM2 &>/dev/null
  21. NUM2_FH=$?
  22. if [ $NUM2_FH -eq 2 ]
  23. then
  24. echo "$NUM2 不是整数 "
  25. exit 2
  26. fi
  27. fi
  28. # 判断输入数值大小
  29. if [ $NUM1 -eq $NUM2 ]
  30. then
  31. echo "$NUM1 = $NUM2"
  32. exit
  33. elif [ $NUM1 -gt $NUM2 ]
  34. then
  35. echo "$NUM1 > $NUM2"
  36. exit
  37. elif [ $NUM1 -lt $NUM2 ]
  38. then
  39. echo "$NUM1 < $NUM2"
  40. fi

2.4 【练习题2】系统内存低于100M邮件报警,加入计划任务,3分钟检查一次。

对于开发程序而言,一般来说应该遵循下面的3步法则。
(1)分析需求
明白开发需求,是完成程序的大前提,因此,分析需求至关重要,一切不以需求为主的程序开发,都是耍流氓的!
(2)设计思路
设计思路就是根据需求,把需求进行拆解,分模块逐步实现,例如本题可以分为如下几步:
1)获取当前系统剩余内存的值(先在命令行实现)。
2)配置邮件报警(可采用第三方邮件服务器)。
3)判断取到的值是否小于100MB,如果小于100MB,就报警(采用if语句)。
4)编码实现Shell脚本。
5)加入crond定时任务,每三分钟检查一次。
(3)编码实现
编码实现就是具体的编码及调试过程,工作中很可能需要先在测试环境下调试,调试好了,再发布到生产环境中。
第一步 先配置邮件服务,保证能够发生邮件

  1. echo 'set from=mail@znix.top smtp=smtp.znix.top smtp-auth-user=mail@znix.top smtp-auth-password=****** smtp-auth=login' >> /etc/mail.rc

发送测试邮件发送

  1. echo "`date +%F_%T`" |mail -s "这是测试邮件" admin@znix.top

Shell编程基础篇-下 - 图1
第二步编写检查脚本

  1. [root@clsn scripts]# cat mem_info.sh
  2. #!/bin/bash
  3. ##############################################################
  4. # File Name: mem_info.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-06 8:42:50
  9. # Description:
  10. ##############################################################
  11. Mem=`free -m |awk 'NR==2{print $NF}'`
  12. host=`hostname`
  13. Ip=`hostname -I`
  14. Date=`date +%F_%T`
  15. mail_file=/tmp/mail.s
  16. dest_user=admin@znix.top
  17. if [ $Mem -lt 100 ]
  18. then
  19. echo "发生时间: $Date" >$mail_file
  20. echo "发生主机: $host 主机IP地址: $Ip " >> $mail_file
  21. echo "内存余量: $Mem M" >> $mail_file
  22. mail -s "【警告】内存不足了呀!" $dest_user < $mail_file
  23. fi

第三步测试脚本(可以修改判断的值)

  1. [root@clsn scripts]# sh mem_info.sh

Shell编程基础篇-下 - 图2
第四步 脚本测试成功,写入定时任务

  1. [root@clsn panduan1]# crontab -l
  2. # 检查内存剩余大小
  3. */3 * * * * /bin/sh /server/scripts/panduan/mem_info.sh &>/dev/null

至此,一个监控脚本就写好了

2.5 【练习题3】模拟编写启动nginx脚本

脚本内容

  1. [root@clsn scripts]# cat nginx.sh
  2. #!/bin/bash
  3. ##############################################################
  4. # File Name: nginx.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-05 20:56:06
  9. # Description:
  10. ##############################################################
  11. . /etc/init.d/functions
  12. StartCheck=`netstat -lntup |grep -c 80`
  13. StartCMD='/application/nginx/sbin/nginx '
  14. StopCMD='/application/nginx/sbin/nginx -s stop '
  15. StatusCheck=`netstat -lntp|grep -c nginx`
  16. ReloadCMD='/application/nginx/sbin/nginx -s reload'
  17. CheckCMD='/application/nginx/sbin/nginx -t'
  18. UsaGe="Usage: $0 {start|stop|status|reload|check}"
  19. COMMAND=$1
  20. if [ $# -ne 1 ]
  21. then
  22. echo $UsaGe && exit 2
  23. fi
  24. if [ $COMMAND = start ]
  25. then
  26. if [ $StartCheck == 1 ]
  27. then
  28. action "启动Nginx失败,端口被占用" /bin/false
  29. else
  30. $StartCMD
  31. action "启动Nginx" /bin/true
  32. fi
  33. elif [ $COMMAND = stop ]
  34. then
  35. $StopCMD &>/dev/null
  36. if [ $? -eq 0 ]
  37. then
  38. action "停止Nginx" /bin/true
  39. else
  40. action "停止Nginx" /bin/false
  41. fi
  42. elif [ $COMMAND = status ]
  43. then
  44. if [ $StatusCheck -eq 1 ]
  45. then
  46. echo "nginx 正在运行..."
  47. else
  48. echo "Nginx 未运行."
  49. fi
  50. elif [ $COMMAND = reload ]
  51. then
  52. $ReloadCMD
  53. action "reload" /bin/true
  54. elif [ $COMMAND = check ]
  55. then
  56. $CheckCMD
  57. else
  58. echo $UsaGe
  59. exit 2
  60. fi

脚本执行过程:
Shell编程基础篇-下 - 图3

2.6 【练习题5】Web及MySQL服务异常监测案例

用if条件语句实现对Nginx Web服务以及MySQL数据库服务是否正常进行检测,如果服务未启动,则启动相应服务。
脚本编写思路:
判断web服务器正常 ↓

  1. 1、进程 ps -ef |grep [n]ginx
  2.  2、端口 netstat ss losf telnet nc nmap
  3.  3curl 页面 返回值
  4.  4curl check.html 的内容

判断mysql服务器正常 ↓

  1. 1、端口 netstat ss losf telnet nc nmap
  2. 2、进程 ps -ef |grep [m]ysql
  3. 3mysql 登录访问看一下
  4. 4mysql insert一个数据 select一个数据

web服务监控脚本示例

  1. [root@clsn scripts]# cat web_check.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: web_check.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-07 10:53:38
  9. # Description:
  10. #############################################################
  11. . /etc/init.d/functions
  12. JinChen=`ps -ef |grep -c [n]ginx`
  13. QiDong='/server/scripts/nginx.sh start'
  14. StatuS=`curl -I -w "%{http_code}\n" -o /dev/null -s 10.0.0.180`
  15. StatuS2=`curl -s 10.0.0.180/check.html|grep -c ok`
  16. StartNginx='/server/scripts/nginx.sh start'
  17. if [ $JinChen -ge 2 ]
  18. then
  19. if [ "$StatuS" -eq 200 ]
  20. then
  21. if [ "$StatuS2" -eq 1 ]
  22. then
  23. action "Nginx 服务运行正常" /bin/true
  24. else
  25. action "请检查chenk.html文件!" /bin/false
  26. fi
  27. else
  28. action "请检查首页文件!" /bin/false
  29. fi
  30. else
  31. action "Nginx 未正常运行!" /bin/false
  32. $StartNginx
  33. fi

脚本执行过程:
Shell编程基础篇-下 - 图4

3. case条件结构语句

3.1 case语法结构

  1. case "字符串变量" in
  2. 1)
  3. 指令1
  4. ;;
  5. 2)
  6. 指令2
  7. ;;
  8. 值*)
  9. 指令
  10. esac

3.2 case与if的对比

case书写方式

  1. case $name in
  2. 1)
  3. 指令1
  4. ;;
  5. 2)
  6. 指令2
  7. ;;
  8. *)
  9. 指令
  10. esac

if书写方式

  1. if [ $name == "值1" ]
  2. then
  3. 指令1
  4. elif [ $name == "值2" ]
  5. then
  6. 指令2
  7. else
  8. 指令
  9. fi

3.3 case值的书写方式

  1. apple)
  2. echo -e "$RED_COLOR apple $RES"
  3. ;;

也可以这样写,输入2种格式找同一个选项

  1. apple|APPLE)
  2. echo -e "$RED_COLOR apple $RES"
  3. ;;

3.4 case语句小结

  • case语句就相当于多分支的if语句。case语句的优势是更规范、易读。
  • case语句适合变量的值少,且为固定的数字或字符串集合。(1,2,3)或(start,stop,restart)。
  • 系统服务启动脚本传参的判断多用case语句,多参考rpcbind/nfs/crond脚本;菜单脚本也可以使用case

    3.5 【练习题1】使用case编写一个菜单脚本

    脚本内容 ```powershell [root@clsn case]# cat menu.sh

    !/bin/bash

    #

    File Name: menu.sh

    Version: V1.0

    Author: clsn

    Organization: http://blog.znix.top

    Created Time : 2017-12-07 14:47:36

    Description:

    #

cat<<EOF

  1. install rsync
  2. install nfs
  3. install mysql
  4. install all EOF

read -p ‘请输入你的选择:’ chs

case $chs in 1) echo install rsync success ;; 2) echo install nfs success ;; 3) echo install mysql success ;; 4) echo install rsync/nfs/mysql success ;; *) echo “你输入有误” esac

  1. 脚本执行过程:<br />![](https://cdn.nlark.com/yuque/0/2021/gif/1484428/1614730735159-d4d24771-5a6f-41dc-9004-e98337ad3d14.gif#align=left&display=inline&height=483&margin=%5Bobject%20Object%5D&originHeight=483&originWidth=1192&size=0&status=done&style=none&width=1192)
  2. <a name="Xumd4"></a>
  3. ## 3.6 【练习题2】输出带有颜色的水果菜单
  4. 脚本内容:
  5. ```powershell
  6. [root@clsn scripts]# cat fruits.sh
  7. #!/bin/bash
  8. #############################################################
  9. # File Name: fruits.sh
  10. # Version: V1.0
  11. # Author: clsn
  12. # Organization: http://blog.znix.top
  13. # Created Time : 2017-12-06 21:23:31
  14. # Description:
  15. #############################################################
  16. cat <<EOF
  17. =======================
  18. 1.apple
  19. 2.pear
  20. 3.banana
  21. 4.exit
  22. =======================
  23. EOF
  24. read -t 10 -p "你要看什么水果:" Menu_Num
  25. case "$Menu_Num" in
  26. 1)
  27. echo -e "\033[31m apple \033[0m"
  28. ;;
  29. 2)
  30. echo -e "\033[32m pear \033[0m"
  31. ;;
  32. 3)
  33. echo -e "\033[33m banana \033[0m"
  34. ;;
  35. 4)
  36. exit
  37. esac

脚本执行过程:
Shell编程基础篇-下 - 图5

3.7 写脚本规范及注意事项

  1. 变量名称不能和系统已经存在的命令等重复 free == > Free
  2. 判断单位要统一
  3. 脚本一行不超过一屏的一半。
  4. 能写成变量的内容尽量写成变量

    4. 练习题

    4.1 【练习题1】监控Memcached缓存服务是否正常

    监控Memcached缓存服务是否正常,模拟用户(web客户端)检测。
    使用nc命令加上set/get来模拟检测。
    memecached安装:http://www.cnblogs.com/clsn/p/7999510.html
    脚本内容: ```powershell [root@clsn scripts]# vim memcache_check.sh

    !/bin/bash

    #

    File Name: memcache_check.sh

    Version: V1.0

    Author: clsn

    Organization: http://blog.znix.top

    Created Time : 2017-12-07 15:50:03

    Description:

    #
    . /etc/init.d/functions . /etc/init.d/run # 函数 jingdutiao 使用 MemPort=netstat -lntp |grep -c 0.0.0.0:11211 Set_Key=’printf “set clsn2017 0 10 8\r\nclsn2018\r\n”|nc 10.0.0.180 11211’ Get_Key=’printf “get clsn2017\r\n” |nc 10.0.0.180 11211 |grep -c clsn2018’ ReStart=’systemctl restart memcached.service’

if [ $MemPort -eq 1 ] then $Set_Key $Get_Key if [ $? -ne 1 ] then action “Memcached 运行正常!” /bin/true else action “Memcached 服务异常!” /bin/false fi else action “服务未启动!” /bin/false $ReStart jingdutiao fi

  1. 脚本执行过程<br />![](https://cdn.nlark.com/yuque/0/2021/gif/1484428/1614730735174-116cd267-5281-48b9-a2c8-35518c8bea13.gif#align=left&display=inline&height=484&margin=%5Bobject%20Object%5D&originHeight=484&originWidth=1202&size=0&status=done&style=none&width=1202)
  2. <a name="1xzML"></a>
  3. ## 4.2 【练习题2】使用(case)编写rsync管理脚本
  4. 写网络服务独立进程模式下Rsync的系统启动脚本,例如:/etc/init.d/rsyncd {start|stop|restart}。<br />**要求:**<br />  1.要使用系统函数库技巧。<br />  2.要用函数,不能一坨💩的方式。<br />  3.centos 6 可被chkconfig管理。<br />**注意:**<br />  服务的停止操作和启动操作之间要有间隔时间,使用sleep 1
  5. ```powershell
  6. pkill 进程
  7. sleep 1
  8. start 服务

rsync服务启动脚本

  1. [root@clsn scripts]# cat rsyncd
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: rsync_admin.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-07 18:39:37
  9. # Description:
  10. #############################################################
  11. . /etc/init.d/functions
  12. . /etc/init.d/run
  13. Rsync_Port=`netstat -lntup |grep -c 0.0.0.0:873`
  14. Rsync_COM1='rsync --daemon'
  15. Rsync_COM2='pkill rsync'
  16. Rsync_Start() {
  17. Rsync_Port1=`netstat -lntup |grep -c 0.0.0.0:873`
  18. if [ $Rsync_Port1 -ne 0 ]
  19. then
  20. action "服务已启动" /bin/false
  21. exit 3
  22. else
  23. $Rsync_COM1
  24. #action "Rsync 启动" /bin/true
  25. QiDong
  26. fi
  27. }
  28. Rsync_Stop() {
  29. Rsync_Port2=`netstat -lntup |grep -c 0.0.0.0:873`
  30. if [ $Rsync_Port2 -eq 0 ]
  31. then
  32. action "服务未启动" /bin/false
  33. exit 3
  34. else
  35. $Rsync_COM2
  36. #action "Rsync 停止" /bin/true
  37. TingZhi
  38. fi
  39. }
  40. Rsync_Status() {
  41. if [ $Rsync_Port -eq 1 ]
  42. then
  43. echo "Rsync 服务运行中..."
  44. else
  45. echo "Rsync 服务未运行"
  46. fi
  47. }
  48. Rsync_Restart() {
  49. Rsync_Stop
  50. Rsync_Start
  51. }
  52. COMMAND=$1
  53. case "$COMMAND" in
  54. start)
  55. Rsync_Start
  56. ;;
  57. stop)
  58. Rsync_Stop
  59. ;;
  60. status)
  61. Rsync_Status
  62. ;;
  63. restart|reload|force-reload)
  64. Rsync_Restart
  65. ;;
  66. *)
  67. echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
  68. exit 2
  69. esac

脚本执行过程
Shell编程基础篇-下 - 图6

4.3 【练习题3】菜单自动化软件部署脚本实践

综合实例:打印选择菜单,按照选择一键安装不同的Web服务。
示例菜单:
[root@oldboy scripts]# sh menu.sh
1.[install lamp]
2.[install lnmp]
3.[exit]
pls input the num you want:
要求:
  1、当用户输入1时,输出“start installing lamp.提示”然后执行/server/scripts/lamp.sh,脚本内容输出”lampis installed”后退出脚本,工作中就是正式lamp一键安装脚本;

  1. echo 'echo lampis installed' > /server/scripts/lamp.sh
  2. chmod +x /server/scripts/lamp.sh

  2、当用户输入2时,输出“start installing lnmp.提示” 然后执行/server/scripts/lnmp.sh输出”lnmpis installed”后退出脚本,工作中就是正式lnmp一键安装脚本;

  1. echo 'echo lnmpis installed' > /server/scripts/lnmp.sh
  2. chmod +x /server/scripts/lnmp.sh

  3、当输入3时,退出当前菜单及脚本;
  4、当输入任何其它字符,给出提示“Input error”后退出脚本;
  5、要对执行的脚本进行相关的条件判断,例如:脚本文件是否存在,是否可执行等判断。
脚本内容

  1. [root@clsn scripts]# cat menu.sh
  2. #!/bin/bash
  3. #############################################################
  4. # File Name: menu.sh
  5. # Version: V1.0
  6. # Author: clsn
  7. # Organization: http://blog.znix.top
  8. # Created Time : 2017-12-07 19:29:30
  9. # Description:
  10. #############################################################
  11. cat <<EOF
  12. 1.[install lamp]
  13. 2.[install lnmp]
  14. 3.[exit]
  15. EOF
  16. read -p "please input the num you want:" Num
  17. case "$Num" in
  18. 1)
  19. if [ -f /server/scripts/lamp.sh ]
  20. then
  21. echo -e "\033[36mstart installing lamp\033[0m"
  22. /server/scripts/lamp.sh
  23. else
  24. echo -e "\033[5;41;37m /server/scripts/lamp.sh 文件不存在 \033[0m"
  25. fi
  26. ;;
  27. 2)
  28. if [ -f /server/scripts/lnmp.sh ]
  29. then
  30. echo -e "\033[36mstart installing lnmp\033[0m"
  31. /server/scripts/lnmp.sh
  32. else
  33. echo -e "\033[5;41;37m /server/scripts/lnmp.sh 文件不存在 \033[0m"
  34. fi
  35. ;;
  36. 3)
  37. exit
  38. ;;
  39. *)
  40. echo -e "\033[31mInput error \033[0m"
  41. exit 2
  42. esac

执行过程
Shell编程基础篇-下 - 图7

4.4 if 与 case 对比

  if 语句类似黑名单,需要把这种错误场景封堵
  case 语句类似白名单,只要把正确结果列完整即可

5. 其他补充说明

5.1 linux中产生随机数的方法

  1. [root@clsn scripts]# echo $RANDOM
  2. 29291
  3. [root@clsn scripts]# echo $RANDOM
  4. 5560
  5. [root@clsn scripts]# echo $RANDOM
  6. 2904

5.2 echo 命令输出带颜色字符

# 彩色字体

  1. echo -e "\033[30m 黑色字 clsn \033[0m"
  2. echo -e "\033[31m 红色字 clsn \033[0m"
  3. echo -e "\033[32m 绿色字 clsn \033[0m"
  4. echo -e "\033[33m 黄色字 clsn \033[0m"
  5. echo -e "\033[34m 蓝色字 clsn \033[0m"
  6. echo -e "\033[35m 紫色字 clsn \033[0m"
  7. echo -e "\033[36m 天蓝字 clsn \033[0m"
  8. echo -e "\033[37m 白色字 clsn \033[0m"

效果示意图
Shell编程基础篇-下 - 图8
# 彩色底纹

  1. echo -e "\033[40;37m 黑底白字 clsn \033[0m"
  2. echo -e "\033[41;37m 红底白字 clsn \033[0m"
  3. echo -e "\033[42;37m 绿底白字 clsn \033[0m"
  4. echo -e "\033[43;37m 黄底白字 clsn \033[0m"
  5. echo -e "\033[44;37m 蓝底白字 clsn \033[0m"
  6. echo -e "\033[45;37m 紫底白字 clsn \033[0m"
  7. echo -e "\033[46;37m 天蓝白字 clsn \033[0m

效果示意图
Shell编程基础篇-下 - 图9
# 特效字体

  1. \033[0m 关闭所有属性
  2. \033[1m 设置高亮度
  3. \033[4m 下划线
  4. \033[5m 闪烁
  5. \033[7m 反显
  6. \033[8m 消隐
  7. \033[30m \033[37m 设置前景色
  8. \033[40m \033[47m 设置背景色
  9. \033[nA 光标上移 n
  10. \033[nB 光标下移 n
  11. \033[nC 光标右移 n
  12. \033[nD 光标左移 n
  13. \033[y;xH 设置光标位置
  14. \033[2J 清屏
  15. \033[K 清除从光标到行尾的内容
  16. \033[s 保存光标位置
  17. \033[u 恢复光标位置
  18. \033[?25l 隐藏光标
  19. \033[?25h 显示光标

部分效果示意图
Shell编程基础篇-下 - 图10

5.3 显示文本中的隐藏字符

使用cat命令查看文本中的隐藏字符

  1. [root@clsn ~]# cat --help
  2. 用法:cat [选项]... [文件]...
  3. 将[文件]或标准输入组合输出到标准输出。
  4. -A, --show-all 等于-vET
  5. -b, --number-nonblank 对非空输出行编号
  6. -e 等于-vE
  7. -E, --show-ends 在每行结束处显示"$"
  8. -n, --number 对输出的所有行编号
  9. -s, --squeeze-blank 不输出多行空行
  10. -t 与-vT 等价
  11. -T, --show-tabs 将跳格字符显示为^I
  12. -u (被忽略)
  13. -v, --show-nonprinting 使用^ M- 引用,除了LFD TAB 之外

使用cat -A查看隐藏的字符

  1. [root@clsn ~]# cat -A /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4$
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6$
  4. 10.0.0.1 mirrors.aliyuncs.com mirrors.aliyun.com$
  5. 10.0.0.180 clsn$

关于隐藏字符常见错误
在windows中编写的脚本换行使用的是 \r\n
但是在linux中使用\n 进行换行

  1. [root@clsn ~]# cat -A windowe.sh
  2. n1=2^M$
  3. n2=1^M$
  4. ^M$
  5. [ $n1 -gt $n2 ] && echo "$n1 > $n2" && exit^M$
  6. [ $n1 -eq $n2 ] && echo "$n1 = $n2" && exit^M$
  7. echo "$n1 < $n2"^M$

使用dos2unix 把windows上的脚本转化linux格式

  1. [root@clsn ~]# dos2unix windowe.sh
  2. dos2unix: converting file windowe.sh to Unix format ...

转换后,脚本的内容隐藏内容改变。

  1. [root@clsn ~]# cat -A windowe.sh
  2. n1=2$
  3. n2=1$
  4. $
  5. [ $n1 -gt $n2 ] && echo "$n1 > $n2" && exit$
  6. [ $n1 -eq $n2 ] && echo "$n1 = $n2" && exit$
  7. echo "$n1 < $n2"$

5.4 排错技巧

sh -x 脚本.sh

  1. -x 开启脚本调试模式

cat -A 文件.txt

  1. -A 查看文件的隐藏字符

5.5 shell 脚本段注释方法

方法一:

  1. <<EOF
  2. 内容
  3. EOF

方法二:

  1. 一行注释方法 : '内容'
  2. 段注释方法
  3. :'
  4. http://blog.znix.top
  5. '

:命令的说明

  1. [root@clsn scripts]# help :
  2. :: :
  3. 空的命令。
  4. 没有效果; 此命令不做任何操作。
  5. 退出状态:
  6. 总是成功。

:命令的应用场景

  1. if 条件
  2. then
  3. :
  4. else
  5. 命令
  6. fi

5.6 其他补充

类进度条效果

  1. yum install -y pv
  2. echo {1..20}|pv -qL 15

clear 命令

  1. 清屏 == ctrl + l

6. 参考文献

http://man.linuxde.net/curl https://www.abcdocker.com/abcdocker/206

http://www.cnblogs.com/clsn/p/7750615.html

http://blog.51cto.com/oldboy/1867160 (部分练习题目来源)