【运维知识高级篇】超详细的Shell编程讲解2(变量切片+统计变量长度+字串删除+字串替换+七种方法进行数值运算+整数比较+多整数比较+文件判断+字符串比对+正则比对+配合三剑客的高阶用法)(二)

简介: 【运维知识高级篇】超详细的Shell编程讲解2(变量切片+统计变量长度+字串删除+字串替换+七种方法进行数值运算+整数比较+多整数比较+文件判断+字符串比对+正则比对+配合三剑客的高阶用法)(二)

3、read交互式传参

1. [root@LB00 Day02]# cat jisuanqi_3.sh
2. #!/bin/bash
3. read -p "请输入第一个数字:" num1
4. read -p "请输入第二个数字:" num2
5. echo $num1+$num2=$[$num1+$num2]
6. echo $num1-$num2=$[$num1-$num2]
7. echo $num1*$num2=$[$num1*$num2]
8. echo $num1/$num2=$[$num1/$num2]
9. echo $num1%$num2=$[$num1%$num2]
10. echo $num1^$num2=$[$num1^$num2]
11. [root@LB00 Day02]# sh jisuanqi_3.sh
12. 请输入第一个数字:9
13. 请输入第二个数字:3
14. 9+3=12
15. 9-3=6
16. 9*3=27
17. 9/3=3
18. 9%3=0
19. 9^3=10

4、交互式传参,可以填运算符

1. [root@LB00 Day02]# cat jisuanqi_4.sh 
2. #!/bin/bash
3. read -p "请输入第一个数字:" num1
4. read -p "请输入运算符号:" fuhao
5. read -p "请输入第二个数字:" num2
6. if [ $fuhao == "+" ]
7. then
8.   echo $num1+$num2=$[$num1+$num2]
9. elif [ $fuhao == "-" ]
10. then
11.   echo $num1-$num2=$[$num1-$num2]
12. elif [ $fuhao == "*" ]
13. then
14.   echo $num1*$num2=$[$num1*$num2]
15. elif [ $fuhao == "/" ]
16. then
17.   echo $num1/$num2=$[$num1/$num2]
18. elif [ $fuhao == "%" ]
19. then
20.   echo $num1%$num2=$[$num1%$num2]
21. elif [ $fuhao == "^" ]
22. then
23.   echo $num1^$num2=$[$num1^$num2]
24. else
25.   echo 没有该运算符号
26. fi
27. [root@LB00 Day02]# sh jisuanqi_4.sh
28. 请输入第一个数字:6
29. 请输入运算符号:+
30. 请输入第二个数字:1
31. 6+1=7
32. [root@LB00 Day02]# sh jisuanqi_4.sh
33. 请输入第一个数字:9
34. 请输入运算符号:/
35. 请输入第二个数字:3
36. 9/3=3

5、赋值传参,可以算小数

将外面参数赋值给变量,又将变量赋值到awk里

1. [root@LB00 Day02]# cat jisuanqi_5.sh
2. #!/bin/bash
3. num1=$1
4. num2=$2
5. echo $num1+$num2=`awk -v num1="$num1" -v num2="$num2" 'BEGIN{print num1+num2}'`
6. echo $num1-$num2=`awk -v num1="$num1" -v num2="$num2" 'BEGIN{print num1-num2}'`
7. echo $num1*$num2=`awk -v num1="$num1" -v num2="$num2" 'BEGIN{print num1*num2}'`
8. echo $num1/$num2=`awk -v num1="$num1" -v num2="$num2" 'BEGIN{print num1/num2}'`
9. echo $num1%$num2=`awk -v num1="$num1" -v num2="$num2" 'BEGIN{print num1%num2}'`
10. echo $num1^$num2=`awk -v num1="$num1" -v num2="$num2" 'BEGIN{print num1^num2}'`
11. [root@LB00 Day02]# sh jisuanqi_5.sh 10 3
12. 10+3=13
13. 10-3=7
14. 10*3=30
15. 10/3=3.33333
16. 10%3=1
17. 10^3=1000
18. 
19. # 其实不用两次赋值的,awk在脚本中使用方式如下
20. 
21. [root@LB00 Day02]# cat jisuanqi_6.sh 
22. #!/bin/bash
23. num1=$1
24. num2=$2
25. echo "$num1+$num2=`awk "BEGIN{print $num1+$num2}"`"
26. echo "$num1-$num2=`awk "BEGIN{print $num1-$num2}"`"
27. echo "$num1*$num2=`awk "BEGIN{print $num1*$num2}"`"
28. echo "$num1/$num2=`awk "BEGIN{print $num1/$num2}"`"
29. echo "$num1%$num2=`awk "BEGIN{print $num1%$num2}"`"
30. echo "$num1^$num2=`awk "BEGIN{print $num1^$num2}"`"
31. [root@LB00 Day02]# sh jisuanqi_6.sh 10 3
32. 10+3=13
33. 10-3=7
34. 10*3=30
35. 10/3=3.33333
36. 10%3=1
37. 10^3=1000

整数比较

一、比较符

-eq        相等

-ge        大于或等于

-gt         大于

-le         小于或等于

-lt          小于

-ne        不相等

二、语法

1、test 整数1 比较符 整数2

1. [root@LB00 ~]# test 1 -eq 1
2. [root@LB00 ~]# echo $?
3. 0    #0即成立,非0不成立
4. [root@LB00 ~]# test 1 -ne 1
5. [root@LB00 ~]# echo $?
6. 1

2、[ 整数1 比较符 整数2 ] 注意两边都有空格

1. [root@LB00 ~]# [ 100 -eq 100 ]
2. [root@LB00 ~]# echo $?
3. 0
4. [root@LB00 ~]# [ 100 -lt 100 ]
5. [root@LB00 ~]# echo $?
6. 1
7. [root@LB00 ~]# [ 100 -lt 100 ] && echo 成立 || echo 不成立
8. 不成立
9. [root@LB00 ~]# [ 100 -eq 100 ] && echo 成立 || echo .成立
10. 成立

3、表达式中都支持变量

1. [root@LB00 ~]# num1=100
2. [root@LB00 ~]# num2=100
3. [root@LB00 ~]# [ $num1 -eq $num2 ] && echo 成立 || echo 不成立
4. 成立

4、表达式中都支持命令

1. [root@LB00 Day02]# [ `echo 100` -lt `cat /etc/passwd|wc -l ` ] && echo 成立 || echo 不成立
2. 不成立
3. [root@LB00 Day02]# cat /etc/passwd|wc -l 
4. 22

5、多整数比较

-o  or  或者

-a  and  并且

注意:在表达式 (())中使用的比较符是> < >= <= != && ||

1. [root@LB00 Day02]# [ 10 -eq 10 -o 100 -gt 20 ] && echo 成立 || echo 不成立
2. 成立
3. [root@LB00 Day02]# [ 10 -eq 10 -o 100 -lt 20 ] && echo 成立 || echo 不成立
4. 成立
5. [root@LB00 Day02]# [ 10 -ne 10 -o 100 -lt 20 ] && echo 成立 || echo 不成立
6. 不成立
7. [root@LB00 Day02]# (( 10 > 2)) && echo 成立 || echo 成立
8. 成立
9. [root@LB00 Day02]# (( 10 != 2 )) && echo 成立 || echo  不成立
10. 成立
11. [root@LB00 Day02]# (( 10 == 2 )) && echo 成立 || echo  不成立
12. 不成立
13. [root@LB00 Day02]# (( 10 == 2 || 5 > 1 )) && echo 成立 || echo 不成立
14. 成立
15. [root@LB00 Day02]# (( 10 == 2 && 5 < 1 )) && echo 成立 || echo 不成立
16. 不成立

三、示例

1、统计磁盘使用率,大于10%则告警发送邮件,小于10%则提示磁盘使用正常,当前使用率是多少

1. [root@LB00 Day02]# df -h
2. Filesystem      Size  Used Avail Use% Mounted on
3. devtmpfs        476M     0  476M   0% /dev
4. tmpfs           487M     0  487M   0% /dev/shm
5. tmpfs           487M   14M  473M   3% /run
6. tmpfs           487M     0  487M   0% /sys/fs/cgroup
7. /dev/sda3        19G  2.0G   17G  11% /
8. /dev/sda1       197M  110M   88M  56% /boot
9. tmpfs            98M     0   98M   0% /run/user/0
10. [root@LB00 Day02]# cat gaojing.sh
11. #!/bin/bash
12. #1、获取磁盘使用率
13. use_disk=$(df -h|grep /dev/sda3|awk '{print $5}')
14. 
15. #2、整数比较
16. if [ ${use_disk%\%} -gt 10 ]
17. then
18.     echo 当前的磁盘使用率:$use_disk > /tmp/disk.log
19.     mail -s "磁盘使用率告警通知" xxx@qq.com < /tmp/disk.log    #需要提前配置好邮箱
20.     i=1
21. else
22.     echo 当前磁盘使用正常,使用率为$use_disk
23. fi
24. 
25. sleep 60      #可以暂停60秒,查看是否恢复
26. 
27. if [ $i -eq 1 && ${use_disk%\%} -lt 10 ]
28. then
29.     echo 恢复......
30. fi

依照上面操作还可以写出内存使用率告警和负载使用告警

2、内存使用率告警

1. [root@LB00 Day02]# free  #里面used除以total乘以100%就是内存使用率
2.               total        used        free      shared  buff/cache   available
3. Mem:         995676      152768      467416       14060      375492      685652
4. Swap:       1048572           0     1048572
5. [root@LB00 Day02]# cat free.sh 
6. #!/bin/bash
7. used=`free | grep Mem | awk '{print $3}'`
8. total=`free | grep Mem | awk '{print $2}'`
9. if [ "$total" -ne "0" ]
10. then
11. free=$((used*100/total))
12. else
13.   echo "Error: Total memory is zero."
14. fi
15. if [ ${free%\%} -gt 15 ]
16. then
17.     echo 当前内存使用率超过15%,为$free%
18. exit
19. fi
20. echo 当前内存使用率正常,为$free%
21. [root@LB00 Day02]# sh free.sh
22. 15
23. 当前内存使用率正常,为15%

3、负载使用率告警

1. [root@LB00 Day02]# cat uptime.sh
2. #!/bin/bash
3. load1=`uptime|awk -F , '{print $(NF-2)}'|awk '{print $3}'`
4. load2=`uptime|awk -F , '{print $(NF-1)}'|awk '{print $1}'`
5. load3=`uptime|awk -F , '{print $NF}'|awk '{print $1}'`
6. load_avg=`awk -v load1=$load1 -v load2=$load2 -v load3=$load3 'BEGIN{print (load1+load2+load3)/3}'`
7. if [ $(echo "$load_avg > 0.5" | bc) -eq 1 ]
8. then
9.     echo 当前1、5、15分钟平均负载超过0.5,为$load_avg
10. exit
11. fi
12. echo 当前1、5、15分钟平均负载正常为$load_avg
13. [root@LB00 Day02]# sh uptime.sh 
14. 当前1、5、15分钟平均负载正常为0.02

文件判断

一、判断符

-f         文件存在则为真

-d        目录存在则为真

-e        文件存在则为真(任意类型)

-r         文件可读则为真

-w        文件可写则为真

-x         文件可执行则为真

二、语法

1、test 判断符 文件或目录

1. [root@LB00 Day02]# test -f /etc/passwd && echo 为真 || echo 为假
2. 为真
3. [root@LB00 Day02]# test -d /etc/passwd && echo 为真 || echo 为假
4. 为假
5. [root@LB00 Day02]# test -e /etc/passwd && echo 为真 || echo 为假
6. 为真
7. [root@LB00 Day02]# test -r /etc/passwd && echo 为真 || echo 为假
8. 为真
9. [root@LB00 Day02]# test -w /etc/passwd && echo 为真 || echo 为假
10. 为真
11. [root@LB00 Day02]# test -x /etc/passwd && echo 为真 || echo 为假
12. 为假

2、[ 判断符 文件或目录 ]

1. [root@LB00 Day02]# [ -f /etc/ ] && echo 为真 || echo  为假
2. 为假
3. [root@LB00 Day02]# [ -d /etc/ ] && echo 为真 || echo  为假
4. 为真
5. [root@LB00 Day02]# [ -e /etc/ ] && echo 为真 || echo  为假
6. 为真
7. [root@LB00 Day02]# [ -r /etc/ ] && echo 为真 || echo  为假
8. 为真
9. [root@LB00 Day02]# [ -w /etc/ ] && echo 为真 || echo  为假
10. 为真
11. [root@LB00 Day02]# [ -x /etc/ ] && echo 为真 || echo  为假
12. 为真

三、示例

1、目录存在则不管,不存在则创建

[root@LB00 Day02]# [ -d 10.0.0.8_2022_02_11 ] || mkdir 10.0.0.8_2022_02_11

2、目录存在则打包

1. [root@LB00 Day02]# [ -d /etc/ ] && mkdir /opt/`hostname`_`date +%F` && tar zcvf /opt/`hostname`_`date +%F`/etc.tar.gz /etc
2. [root@LB00 Day02]# tree /opt/
3. /opt/
4. └── LB00_2023-05-15
5.     └── etc.tar.gz
6. 
7. 1 directory, 1 file

3、bash脚本变量在当前shell中调用

1. [root@LB00 Day02]# cat env.sh 
2. num1=100
3. num2=200
4. num3=300
5. [root@LB00 Day02]# [ -f env.sh ] && source env.sh && echo $num1  #夫shell调用子shell变量
6. 100
7. 
8. [root@LB00 Day02]# cat env.sh
9. num1=100
10. num2=200
11. [root@LB00 Day02]# cat test.sh
12. #!/bin/bash
13. [ -f /server/scripts/Day02/env.sh ] && . /server/scripts/Day02/env.sh #不同子shell之间调用
14. echo $num1+$num2=$[$num1 + $num2]
15. [root@LB00 Day02]# sh test.sh 
16. 100+200=300
17. 
18. [root@LB00 Day02]# cat ~/.bash_profile     #-f系统案例
19. # .bash_profile    
20. 
21. # Get the aliases and functions
22. if [ -f ~/.bashrc ]; then
23.   . ~/.bashrc
24. fi
25. ......

字符串比对

==、!=,也可以结合-o、-a

-z,检查字符串是否为空,字符串为空为真,-n,检查字符串是否为非空,字符串不为空为真

注意使用变量比对大部分情况下要加引号,特别是read的变量,否则直接回车不输入信息就会报错

1. [root@LB00 Day02]# [ root == root ] && echo 等于 || echo 不等于
2. 等于
3. [root@LB00 Day02]# [ root == roo ] && echo 等于 || echo 不等于
4. 不等于
5. [root@LB00 Day02]# [ root == roo -o yes == yes ] && echo 等.于 | echo 不等于
6. 等于
7. [root@LB00 Day02]# [ -z "" ] && echo 字符串空 || echo 字符串非空
8. 字符串空
9. [root@LB00 Day02]# [ -z "1" ] && echo 字符串空 || echo 字符串非空
10. 字符串非空
11. [root@LB00 Day02]# [ -n "" ] && echo 字符串非空 || echo 字符串空
12. 字符串空
13. [root@LB00 Day02]# [ -n "1" ] && echo 字符串非空 || echo 字符串空
14. 字符串非空

正则比对

=~ 模糊匹配

1. [root@LB00 Day02]# [[ root =~ roo ]] && echo 匹配成功 || echo 匹配失败
2. 匹配成功
3. [root@LB00 Day02]# [[ root =~ r ]] && echo 匹配成功 || echo 匹配失败
4. 匹配成功
5. [root@LB00 Day02]# [[ root =~ ^r ]] && echo 匹配成功 || echo 匹配失败
6. 匹配成功
7. [root@LB00 Day02]# [[ root =~ ^r$ ]] && echo 匹配成功 || echo 匹配失败
8. 匹配失败
9. [root@LB00 Day02]# [[ root =~ ^r.*t$ ]] && echo 匹配成 功 | echo 匹配失败
10. 匹配成功
11. [root@LB00 Day02]# [[ root =~ [a-z] ]] && echo 匹配成功 || eccho 匹配失败
12. 匹配成功
13. [root@LB00 Day02]# [[ root =~ [0-9] ]] && echo 匹配成功 || echo 匹配失败
14. 匹配失败
15. [root@LB00 Day02]# [[ root =~ ^[a-z]+$ ]] && echo 匹配成功 || echo 匹配失败
16. 匹配成功
17. [root@LB00 Day02]# [[ root1 =~ ^[a-z]+$ ]] && echo 匹配成功 | echo 匹配失败
18. 匹配失败
19. [root@LB00 Day02]# [[ r1o2o3t =~ [0-9] ]] && echo 匹配 成功 | echo 匹配失败
20. 匹配成功
21. [root@LB00 Day02]# [[ r1o2o3t =~ [a-z]+ ]] && echo 匹.成功 || echo 匹配失败
22. 匹配成功
23. [root@LB00 Day02]# [[ r1o2o3t =~ ^[a-z]+$ ]] && echo .配成功 || echo 匹配失败
24. 匹配失败
25. [root@LB00 Day02]# [[ r1o2o3t =~ ^[a-z]$ ]] && echo 匹 配成功 || echo 匹配失败
26. 匹配失败

示例一:控制输入内容格式

控制姓名年龄的格式,年龄控制在18-256之间可以正常往后运行

1. [root@LB00 Day02]# cat read.sh
2. #!/bin/bash
3. read -p "请输入您的姓名:" name
4. if [[ ! $name =~ ^[a-z]+$ ]]
5. then
6.     echo "请输入正确姓名,不能有数字"
7. exit
8. fi
9. read -p "请输入您的年龄:" age
10. if [[ ! $age =~ ^[0-9]+$ ]]
11. then
12.     echo "请输入正确年龄,不能有英文"
13. exit
14. fi
15. if ! [ $age -ge 18 -a $age -le 256 ]
16. then
17.     echo "您的年龄不符合标准"
18. exit
19. fi
20. echo "姓名为" $name "年龄为" $age
21. [root@LB00 Day02]# sh read.sh
22. 请输入您的姓名:q
23. 请输入您的年龄:18
24. 姓名为 q 年龄为 18
25. [root@LB00 Day02]# sh read.sh 
26. 请输入您的姓名:q1q
27. 请输入正确姓名,不能有数字
28. [root@LB00 Day02]# sh read.sh
29. 请输入您的姓名:q
30. 请输入您的年龄:17
31. 您的年龄不符合标准
32. [root@LB00 Day02]# sh read.sh 
33. 请输入您的姓名:qq
34. 请输入您的年龄:333
35. 您的年龄不符合标准

扩展(配合三剑客取系统信息)

写脚本常常需要三剑客命令的配合,所以我们进行如下练习,练习使用三剑客命令。

写一个脚本,统计出系统主机名称,eth0IP地址,公网ip地址,平台信息,系统版本号,内核版本号,磁盘使用率,内存使用率。

这种脚本可以放到/etc/profile中,xshell一连接就能看到,工作中常常需要看负载信息,这样一连接信息都出来了,比较方便。

1. [root@LB00 Day02]# cat tongji.sh 
2. #!/bin/bash
3. hostname=$(hostname)
4. eth0_ip=$(ip a|grep eth0|grep inet|awk '{print $2}')
5. gong_ip=$(curl -s cip.cc|awk 'NR==1{print $3}')
6. pingtai=$(hostnamectl|grep Virtualization|awk '{print $2}')
7. linux_banben=$(cat /etc/redhat-release)
8. linux_neihe=$(hostnamectl|grep Kernel|awk '{print $2,$3}')
9. load1=`uptime|awk -F , '{print $(NF-2)}'|awk '{print $3}'`
10. load2=`uptime|awk -F , '{print $(NF-1)}'|awk '{print $1}'`
11. load3=`uptime|awk -F , '{print $NF}'|awk '{print $1}'`
12. load_avg=`awk -v load1=$load1 -v load2=$load2 -v load3=$load3 'BEGIN{print (load1+load2+load3)/3}'`
13. free=$(free | grep Mem | awk '{print $3/$2 *100}')
14. use_disk=$(df -h|grep /dev/sda3|awk '{print $5}')
15. 
16. echo 系统主机名称为:$hostname
17. echo eth0的IP为:$eth0_ip
18. echo 公网IP为:$gong_ip
19. echo 平台信息为:$pingtai
20. echo 系统版本为:$linux_banben
21. echo 内核版本为:$linux_neihe
22. echo 1,5,15分钟平均负载为:$load_avg
23. echo 内存使用率为:$free%
24. echo 磁盘使用率为:$use_disk
25. [root@LB00 Day02]# sh tongji.sh 
26. 系统主机名称为:LB00
27. eth0的IP为:10.0.0.4/24
28. 公网IP为:123.112.17.24
29. 平台信息为:vmware
30. 系统版本为:CentOS Linux release 7.9.2009 (Core)
31. 内核版本为:Linux 3.10.0-1160.el7.x86_64
32. 1,5,15分钟平均负载为:0.02
33. 内存使用率为:15.5713%
34. 磁盘使用率为:11%
35. [root@LB00 Day02]# scp tongji.sh 10.0.0.7:/root/
36. 
37. [root@Web01 ~]# sh tongji.sh 
38. 系统主机名称为:Web01
39. eth0的IP为:10.0.0.7/24
40. 公网IP为:123.112.17.24
41. 平台信息为:vmware
42. 系统版本为:CentOS Linux release 7.9.2009 (Core)
43. 内核版本为:Linux 3.10.0-1160.el7.x86_64
44. 1,5,15分钟平均负载为:0.0233333
45. 内存使用率为:50.3111%
46. 磁盘使用率为:17%
47. 
48. [root@LB00 Day02]# tail -1 /etc/profile
49. sh /server/scripts/Day02/tongji.sh


我是koten,10年运维经验,持续分享运维干货,感谢大家的阅读和关注!

目录
相关文章
|
4天前
|
Shell Android开发
Android系统 adb shell push/pull 禁止特定文件
Android系统 adb shell push/pull 禁止特定文件
16 1
|
18天前
|
存储 运维 Shell
shell中for while until 三种循环的用法
shell编程中,有几种常见的循环结构,包括for循环、while循环和until循环,总的来说,循环shell编程中扮演着至关重要的角色,它们使得自动化任务变得更加容易,提高了效率,并且可以处理各种各样的编程需求。
shell中for while until 三种循环的用法
|
6天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
33 3
|
10天前
|
监控 Shell 开发工具
Shell编程
Shell编程
|
18天前
|
Shell Perl
shell学习(九) 【shell sed用法】
shell学习(九) 【shell sed用法】
9 0
|
30天前
|
存储 Java Shell
bigdata-04-shell编程基础
bigdata-04-shell编程基础
13 0
|
1月前
|
Shell Linux C++
【Shell 编程设计】 编写自己的清理后台的Shell脚本
【Shell 编程设计】 编写自己的清理后台的Shell脚本
32 1
|
7月前
|
缓存 运维 Linux
Linux(CentOS)运维脚本工具集合
Linux(CentOS)运维脚本工具集合
148 2
|
24天前
|
运维 Linux Shell
linux运维常用命令
linux运维常用命令
|
1月前
|
监控 网络协议 Linux
Linux 命令大全 & CentOS常用运维命令
Linux 命令大全 & CentOS常用运维命令
157 0