建议用 .sh 结尾,第一行用 #!/bin/bash 来指定脚本的运行环境

  1. #!/bin/bash
  2. #Auther: cao
  3. #Created Time: 2021/08/14 16:30
  4. #Script Description: oracl install

一、语法

1、特殊符号

  1. ~ 用户的家目录
  2. ! 执行历史命令 !! 执行上一条命令
  3. $ 变量中取内容符
  4. + - * / % 数学运算加、减、乘、除、取余
  5. & 后台执行
  6. * 匹配所有
  7. ? 匹配除回车以外的第一个字符
  8. ; 可以在shell中一行执行多个命令,命令之间用 ; 隔开
  9. | 管道符 上一个命令的输出作为下一个命令的输入 cat filename | grep "abc"
  10. \ 转义符
  11. `` 反引号 命令中执行命令 echo "today is:`date +%F`"
  12. '' 单引号,字符串可以用单引号,单引号是强引,不解释变量
  13. "" 双引号,字符串可以用双引号,单引号是弱引,可以变量传参
  14. > 重定向输入 覆盖原数据
  15. >> 重定向追加输入,在源数据的末尾加上
  16. < 重定向输出 wc < /etc/passwd
  17. << 重定向追加输出 fdisk /dev/sdb <<EOF ...... EOF
  18. exprlet 算数运算
  19. $(()) 算数运算 $((10-2))
  20. exit num 退出脚本,释放系统资源,并返回一个num数值(1-255) 返回值可以用 $? 来查询

1.1、磁盘分区案例(EOF)

  1. #!/bin/bash
  2. # 需要交互的内容顶格写入EOF块中
  3. fdisk /dev/sdb <<EOF
  4. n
  5. p
  6. 3
  7. +534M
  8. W
  9. EOF

1.2、判断是否位整数(expr let)

  1. expr 7 + 1 &> /dev/null ; echo $?
  2. # 结果0为整数,非0不为整数
  3. let sum=1+1 ; echo $sum
  4. # let只能整数做计算

1.3、查询内存使用率(bc运算,scale截取小数点位数)

  1. echo "当前内存的使用率是:`echo "scale=2;141*100/7966"|bc`%"

2、格式化输出

2.1、echo

命令选项: -n 不换行 echo -n “date:”;date +%F -e 解释转义字符,就是解释输出一个变量

转义字符: \a 发出警告声 \t 插入tab \n 换行且光标移至行首 \b 删除前一个字符

\c 最后不加上换行符号 \f 换行但光标仍停留在原来的位置 \r 光标移至行首但不换行 \v 与 \f 相同 \插入\字符 \nnn插入nnn(八进制)所代表的ASCII字符 -help 显示帮助信息 -version 显示版本信息

  1. #!/bin/bash
  2. # -e来实现倒计时
  3. for time in `seq 9 -1 0`;do
  4. echo -n -e "\b$time"
  5. sleep 1
  6. done

2.2、字体颜色

  1. shell脚本中echo显示内容带颜色显示,echo显示带颜色,需要使用参数-e
  2. 格式: echo -e "\033[字背景颜色;文字颜色m字符串\033[0m"
  3. 例如: echo -e "\033[41;36m something here \033[0m"
  4. 其中41的位置代表底色, 36的位置是代表字的颜色
  5. 注:
  6.   1、字背景颜色和文字颜色之间是英文的""
  7.   2、文字颜色后面有个m
  8.   3、字符串前后可以没有空格,如果有的话,输出也是同样有空格
  9. 例:
  10.   echo -e \033[31m 红色字 \033[0m
  11.   echo -e \033[34m 黄色字 \033[0m
  12.   echo -e \033[41;33m 红底黄字 \033[0m
  13.   echo -e \033[41;37m 红底白字 \033[0m
  14.   
  15. 字颜色:30—–37
  16.   echo -e \033[30m 黑色字 \033[0m
  17.   echo -e \033[31m 红色字 \033[0m
  18.   echo -e \033[32m 绿色字 \033[0m
  19.   echo -e \033[33m 黄色字 \033[0m
  20.   echo -e \033[34m 蓝色字 \033[0m
  21.   echo -e \033[35m 紫色字 \033[0m
  22.   echo -e \033[36m 天蓝字 \033[0m
  23.   echo -e \033[37m 白色字 \033[0m
  24.   
  25. 字背景颜色范围:40—–47
  26.   echo -e \033[40;37m 黑底白字 \033[0m
  27.   echo -e \033[41;37m 红底白字 \033[0m
  28.   echo -e \033[42;37m 绿底白字 \033[0m
  29.   echo -e \033[43;37m 黄底白字 \033[0m
  30.   echo -e \033[44;37m 蓝底白字 \033[0m
  31.   echo -e \033[45;37m 紫底白字 \033[0m
  32.   echo -e \033[46;37m 天蓝底白字 \033[0m
  33.   echo -e \033[47;30m 白底黑字 \033[0m
  34.   
  35. 最后面控制选项说明
  36.   \033[0m 关闭所有属性
  37.   \033[1m 设置高亮度
  38.   \033[4m 下划线
  39.   \033[5m 闪烁
  40.   \033[7m 反显
  41.   \033[8m 消隐
  42.   \033[30m \33[37m
  43. 设置前景色
  44.   \033[40m \33[47m 设置背景色
  45.   \033[nA 光标上移n
  46.   \033[nB 光标下移n
  47.   \033[nC 光标右移n
  48.   \033[nD 光标左移n
  49.   \033[y;xH设置光标位置
  50.   \033[2J 清屏
  51.   \033[K 清除从光标到行尾的内容
  52.   \33[s 保存光标位置
  53.   \033[u 恢复光标位置
  54.   \033[?25l 隐藏光标
  55.   \033[?25h 显示光标

3、交互

让用户输入

3.1、read

-p 打印信息 -t 限定时间 -s 不回显 -n 输入字符个数

  1. #!/bin/bash
  2. #echo -n "name:"
  3. #read name
  4. read -p "name:" name
  5. echo -n "password:"
  6. read -s -t5 -n6 pwd
  7. echo "名字是:$name 密码是:$pwd"

4、变量

将字符串值临时存放在内存变量里,即变量和字符串值是对照关系

4.1、变量的分类

  1. 本地变量:用户私有变量,只有本用户可以使用,保存在家目录下的.bash_profile、.bashrc文件中
  2. 全局变量:所有用户都可以使用,保存在/etc/profile、/etc/bashrc文件中
  3. 用户自定义变量:用户自定义,比如脚本中的变量
  4. 变量名命名规则:
  5. 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  6. 中间不能有空格,可以使用下划线(_)。
  7. 不能使用标点符号。
  8. 不能使用bash里的关键字(可用help命令查看保留关键字)。

4.2、变量的基本使用

  1. 变量格式:变量名=值 (在shell编程中的变量名和等号之间不能有空格)
  2. 读取方法:$变量名
  3. 取消变量:unset 变量名
  4. 全局变量:export name='baism'
  5. 本地永久变量:tail -1 ~/.bash_profile
  6. 全局永久变量:tail -1 /etc/profile

4.3、特殊变量

  1. $* 代表所有参数,其间隔为IFS内参数的第一个字元
  2. $@ * 类同,不同之处在于不参照IFS
  3. %# 代表参数数量
  4. $ 执行上一个指令的返回值
  5. $~ 最近执行的 foreground pipeline 的选项参数
  6. $$ 本身的 Process ID
  7. $ 执行上一个背景指令的PID
  8. $_ 显示出最佳的一个执行命令
  9. $N shell脚本的第几个外传参数(0为脚本名称)

5、数组

可以将多个值赋予给一个变量,用索引区分

5.1、数组的基本使用

  1. 数组名称=(元素1 元素2 元素3 ...)
  2. 取值:${数组名称}[索引] 默认第一个从0开始
  3. 查看数组:declare -A 数组名
  4. 访问数组元数:
  5. # echo ${array1[0]} 访问数组中的第一个元素
  6. # echo ${array1[@]} 访问数组中所有元素 等同于 echo ${array1[*]}
  7. # echo ${#array1[@]} 统计数组元素的个数
  8. # echo ${!array2[@]} 获取数组元素的索引
  9. # echo ${array1[@]:1} 从数组下标1开始
  10. # echo ${array1[@]:1:2} 从数组下标1开始,访问两个元素

5.2、关联数组

  1. 一: 一次赋一个值 数组名[索引]=变量值
  2. ass_array1[index1]=pear
  3. ass_array1[index2]=apple
  4. ass_array1[index3]=orange
  5. ass_array1[index4]=peach
  6. 二: 一次赋多个值
  7. ass_array2=([index1]=tom [index2]=jack [index3]=alice [index4]=’bash shell’)

5.3、案例

  1. /bin/bash
  2. for ((i=0;i<3;i++))
  3. do
  4. read -p "输入第$((i + 1))个人名: " name[$i]
  5. read -p "输入第$[$i + 1]个年龄: " age[$i]
  6. read -p "输入第`expr $i + 1`个性别: " gender[$i]
  7. done
  8. clear
  9. echo -e "\t\t\t\t学员查询系统"
  10. while :
  11. do
  12. cp=0
  13. # echo -e "\t\t\t\t学员查询系统"
  14. read -p "输入要查询的姓名: " xm
  15. [ $xm == "Q" ]&&exit
  16. for ((i=0;i<3;i++))
  17. do
  18. if [ "$xm" == "${name[$i]}" ];then
  19. echo "${name[$i]} ${age[$i]} ${gender[$i]}"
  20. cp=1
  21. fi
  22. done
  23. [ $cp -eq 0 ]&&echo "not found student"
  24. done

6、流程控制

6.1、判断比较符号

  1. 数学判断
  2. -eq 等于
  3. -gt 大于
  4. -lt 小于
  5. -ge 大于或等于
  6. -le 小于或等于
  7. -ne 不等于
  8. 字符串判断(字符串要用引号引起来)
  9. == 等于
  10. != 不等于
  11. -n 检查字符串的禅古是否大于0
  12. -z 检查字符串的长度是否为0
  13. 文件判断
  14. -d 检查文件是否存在且为目录
  15. -e 检查文件是否存在
  16. -f 检查文件是否存在且为文件
  17. -r 检查文件是否存在且可读
  18. -s 检查文件是否存在且不为空
  19. -w 检查文件是否存在且可写
  20. -x 检查文件是否存在且可执行
  21. -O 检查文件是否存在且被当前用户所拥有
  22. -G 检查文件是否存在且默认组为当前用户组
  23. test file1 -nt file2;echo $? 检查file1是否比file2
  24. test file1 -ot file2;echo $? 检查file1是否比file2
  25. 逻辑判断
  26. &&
  27. ||
  28. !
  29. 赋值判断
  30. = 赋值运算符 a=10 name="cao"

6.2、if语法

  1. 1、一步判断:
  2. if [ 条件 ]
  3. then
  4. 满足条件后的执行语句
  5. fi
  6. 例:
  7. if [ ! -d /usr/local/cao ]
  8. then
  9. mkdir /usr/local/cao
  10. echo "Create Directory is OK"
  11. fi
  12. 2、二种判断:
  13. if [ 条件 ]
  14. then
  15. 满足条件后的执行语句
  16. else
  17. 不满足的执行语句
  18. fi
  19. 3、三种或以上判断:
  20. if [ 条件 ]
  21. then
  22. 满足条件后的执行语句
  23. elif [ 条件 ]
  24. then
  25. 满足elif条件后的执行语句
  26. else
  27. 不满足执行
  28. fi

6.3、if高级应用

  1. 1、条件符号使用双圆括号,可以在条件中植入数学表达式
  2. 双小圆括号中的比较运算符 使用的是我们传统的比较运算符(>,>=,==,<,<=,!=)
  3. #!/bin/bash
  4. if (( 1+1 == 1 ));then
  5. echo "结果相等"
  6. else
  7. echo “结果不等”
  8. fi
  9. 2、使用双方括号,可以在条件中使用通配符
  10. 为字符串提供高级功能,模式匹配 r* 匹配r开头的字符串
  11. #!/bin/bash
  12. for var in ab ac rx bs rvv vr
  13. do
  14. if [[ "$var" == r* ]];then
  15. echo "$var"
  16. fi
  17. done

6.4、for循环

  1. 1、常规式写法
  2. for var in value1 value2 .....
  3. do
  4. commands
  5. done
  6. 例:
  7. for i in `seq 1 9`;do
  8. echo "$i"
  9. done
  10. 2C式写法
  11. for (( 变量;条件;自增减运算 ));do
  12. 代码块
  13. done
  14. 3、无限循环
  15. for ((;;));do
  16. 代码块
  17. done

6.5、循环的控制语句

  1. sleep N 脚本执行到这里休眠N
  2. continue 跳过本次循环
  3. break 终止本次循环(可以在后边加数字,表示终止第几层的循环)

6.6、while循环

  1. 当条件为true循环,为false停止
  2. while [ 条件 ]:do
  3. 代码块
  4. done
  5. while遍历文本内容:(./test.sh test.sh)
  6. #!/bin/bash
  7. while read i;do
  8. echo "$i"
  9. done < $1
  10. while读出文件中的列,IFS指定默认的列分隔符
  11. #!/bin/bash
  12. IFS=$":"
  13. while read f1 f2 f3 f4 f5 f6;do
  14. echo "$f1 $f2 $f3 $f4"
  15. done < /etc/passwd

6.7、utile循环

  1. 当条件为false循环,为true停止
  2. untile [ 条件 ]:do
  3. 代码块
  4. done

6.8、case语句

  1. case 变量 in
  2. 条件1)
  3. 执行代码块
  4. ;;
  5. 条件2)
  6. 执行代码块
  7. ;;
  8. ......
  9. esac
  10. 例:
  11. read -p "num:" n
  12. case $n in
  13. 1)
  14. echo "你好"
  15. ;;
  16. 2)
  17. echo "我好"
  18. ;;
  19. *)
  20. echo "bye bye"
  21. ;;
  22. esac

二、函数

  1. 函数的两种定义 函数名(){} function 函数名{}
  2. start () {
  3. echo "我在这里定义了函数"
  4. }
  5. start

三、实战

1、nginx启动管理脚本

  1. #!/bin/bash
  2. #=====================variables
  3. nginxdoc="/usr/local/nginx"
  4. nginxd="$nginxdoc/sbin/nginx"
  5. pid="$nginxdoc/logs/nginx.pid"
  6. conf="$nginxdoc/conf/nginx.conf"
  7. #====================function
  8. mystart () {
  9. if [ -f $pid ] && pstree -p |grep `cat $pid` &>/dev/null;then
  10. echo "nginx already run..."
  11. exit 0
  12. else
  13. if $nginxd ;then
  14. echo -e "nginx start\t\t\t\t[\033[32m OK \033[0m]"
  15. else
  16. echo -e "nginx start\t\t\t\t[\033[31m FAIL \033[0m]"
  17. fi
  18. fi
  19. }
  20. mystop () {
  21. if [ -f $pid ] && pstree -p |grep `cat $pid` &>/dev/null;then
  22. if killall -s QUIT $nginxd;then
  23. echo -e "nginx stop\t\t\t\t[\033[32m OK \033[0m]"
  24. else
  25. echo -e "nginx stop\t\t\t\t[\033[31m FAIL \033[0m]"
  26. fi
  27. else
  28. echo "nginx already stop...."
  29. fi
  30. }
  31. myrestart () {
  32. mystop;sleep 2 ;mystart
  33. }
  34. myreload () {
  35. if [ -f $pid ] && pstree -p |grep `cat $pid` &>/dev/null;then
  36. if killall -s HUP $nginxd;then
  37. echo -e "nginx reload\t\t\t\t[\033[32m OK \033[0m]"
  38. else
  39. echo -e "nginx reload\t\t\t\t[\033[31m FAIL \033[0m]"
  40. fi
  41. else
  42. echo "nginx is stop...."
  43. fi
  44. }
  45. mystatus () {
  46. if [ -f $pid ] && pstree -p |grep `cat $pid` &>/dev/null;then
  47. echo "nginx is open"
  48. else
  49. echo "nginx is stop"
  50. fi
  51. }
  52. #===================main
  53. #calld function
  54. case $1 in
  55. start|START)
  56. mystart
  57. ;;
  58. stop) mystop ;;
  59. restart) myrestart ;;
  60. reload) myreload ;;
  61. status) mystatus ;;
  62. esac

2、正则表达式

  1. . 匹配除回车以外的任意字符
  2. ( ) 字符串分组
  3. [ ] 定义字符类,匹配括号中的一个字符
  4. [ ^ ] 表示否定括号中出现字符类中的字符,取反。
  5. \ 转义字符
  6. * 某个字符之后加星号表示该字符出现 0次或多次
  7. ? 与星号相似,但略有变化,表示该字符出现 0次或1
  8. + 与星号相似,表示其前面字符出现 1次或多次
  9. {n,m} 某个字符之后出现,表示该字符最少n次,最多m
  10. {m} 正好出现了m
  11. POSIX特殊字符(都是匹配一个字节):
  12. [:alnum:] 匹配任意字母字符0-9 a-z A-Z
  13. [:alpha:] 匹配任意字母,大写或小写
  14. [:digit:] 数字 0-9
  15. [:graph:] 非空字符( 非空格控制字符)
  16. [:lower:] 小写字符a-z
  17. [:upper:] 大写字符A-Z
  18. [:cntrl:] 控制字符
  19. [:print:] 非空字符( 包括空格)
  20. [:punct:] 标点符号
  21. [:blank:] 空格和TAB字符
  22. [:xdigit:] 16 进制数字
  23. [:space:] 所有空白字符( 新行、空格、制表符)
  24. 第一个中括号是匹配符[] 匹配中括号中的任意一个字符,第二个[]是格式 如[:digit:]
  25. egrep "^a[[:alnum:]]c$" file
  26. 案例一 匹配合法的IP地址
  27. egrep ‘^((25[0-5]|2[0-4][[:digit:]]|[01]?[[:digit:]][[:digit:]]?).){3}(25[0-5]|2[0-4][[:digit:]]|[01]?[[:digit:]][[:digit:]]?)$ color ip_base
  28. 案例二 匹配座机电话号码
  29. egrep “^[[:graph:]]{12}$ number |egrep “^(0[1-9][0-9][0-9]?)-[1-9][0-9]{6,7}$

3、sed文件行操作

对文本中的行进行操作,默认是修改缓存数据而不是源文件

  1. 语法:
  2. sed [options] '{command}[flags]' [filename]
  3. 命令选项
  4. -e script 将脚本中指定的命令添加到处理输入时执行的命令中 多条件,一行中要有多个操作
  5. -f script 将文件中指定的命令添加到处理输入时执行的命令中,一行一个命令
  6. -n 抑制自动输出,只显示修改的内容
  7. -i 编辑文件内容
  8. -i.bak 修改时同时创建.bak备份文件。
  9. -r 使用扩展的正则表达式
  10. ! 取反 (跟在模式条件后与shell有所区别)
  11. sed常用内部命令
  12. a 在匹配后面添加
  13. i 在匹配前面添加
  14. p 打印
  15. d 删除
  16. s 查找替换
  17. c 更改
  18. y 转换 N D P
  19. flags
  20. 数字 表示新文本替换的模式
  21. g 表示用新文本替换现有文本的全部实例
  22. p 表示打印原始的内容
  23. w filename: 将替换的结果写入文件
  24. 例:将data1文本中4 the一行后面插入hello world
  25. sed '/4 the/a hello world' data1
  26. 例:将nginx.conf中#开头,包含#,以空格开头的全删掉
  27. sed -r '/(^#|#|^$)/d' nginx.conf
  28. 例:将data1文本中cat替换成dog
  29. sed 's/cat/dog/' data1
  30. 技巧1:打印行号
  31. sed -n '$=' data1

4、DNS检测WEB状态,并通过DNS对域名做负载均衡

  1. #!/bin/bash
  2. CP1=0
  3. CP2=0
  4. while :
  5. do
  6. #tong
  7. ping -c1 192.168.18.240 > /dev/null
  8. if [ $? -eq 1 ] && [ $CP1 -eq 0 ]
  9. then
  10. sed -i '/192.168.18.240/s/^/;/' /var/named/baidu.zone
  11. /etc/init.d/named reload
  12. CP1=1
  13. fi
  14. #butong
  15. ping -c1 192.168.18.240 > /dev/null
  16. if [ $? -eq 0 ] && [ $CP1 -eq 1 ]
  17. then
  18. sed -i '/192.168.18.240/s/;//' /var/named/baidu.zone
  19. /etc/init.d/named reload
  20. CP1=0
  21. fi
  22. ping -c1 192.168.18.241 > /dev/null
  23. if [ $? -eq 1 ] && [ $CP2 -eq 0 ]
  24. then
  25. sed -i '/192.168.18.241/s/^/;/' /var/named/baidu.zone
  26. /etc/init.d/named reload
  27. CP2=1
  28. fi
  29. ping -c1 192.168.18.241 > /dev/null
  30. if [ $? -eq 0 ] && [ $CP2 -eq 1 ]
  31. then
  32. sed -i '/192.168.18.241/s/;//' /var/named/baidu.zone
  33. /etc/init.d/named reload
  34. CP2=0
  35. fi
  36. sleep 5
  37. done

5、awk输出流操作

awk是一种可以处理数据、产生格式化报表的语言,功能十分强大。awk 认为文件中的每一行是一条记录 记录与记录的分隔符为换行符,每一列是一个字段 字段与字段的分隔符默认是一个或多个空格或tab制表符.

awk的工作方式是读取数据,将每一行数据视为一条记录(record)每条记录以字段分隔符分成若干字段,然后输出各个字段的值.

  1. awk [options] [BEGIN]{program}[END] [file]
  2. 常用命令选项
  3. -F fs 指定描绘一行中数据字段的文件分隔符 默认为空格
  4. -f file 指定读取程序的文件名
  5. -v var=value 定义awk程序中使用的变量和默认值
  6. 注意:awk 程序脚本由左大括号和右大括号定义。脚本命令必须放置在两个大括号之间。由于awk命令行假定脚本是单文本字符串,所以必须将脚本包括在单引号内。
  7. awk程序运行优先级是:
  8. 1)BEGIN: 在开始处理数据流之前执行,可选项
  9. 2)program: 如何处理数据流,必选项
  10. 3)END: 处理完数据流后执行,可选项
  11. 例:awk -F ":" 'NR==1{print $1 "-" $2 "-" $3}' passwd
  12. 例:head -2 /proc/meminfo | awk 'NR==1{z=$2}NR==2{f=$2}END{print(z-f)*100/z "%"}'
  13. $0 表示整行文本
  14. $1 表示文本行中的第一个数据字段
  15. $2 表示文本行中的第二个数据字段
  16. $N 表示文本行中的第N个数据字段
  17. $NF 表示文本行中的最后一个数据字段
  18. NR: 指定行号
  19. 例:awk '{print $0}' test
  20. 例:awk 'NR==3{print $0}' test
  21. 赋值运算 =
  22. 比较运算 > >= == < <= !=
  23. 数学运算 + - / % * ++
  24. 逻辑运算 && ||
  25. 匹配运算 ~ !~
  26. FIELDWIDTHS 以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
  27. FS 输入字段分隔符号
  28. OFS 输出字段分隔符号
  29. RS 输入记录分隔符
  30. ORS 输出记录分隔符号
  31. if 判断语句
  32. for 循环语句
  33. while 循环语句
  34. dowhile 语句
  35. break 循环控制停止

6、awk小技巧

  1. [root@www ~]# cat test
  2. 1 the quick brown fox jumps over the lazy cat . dog
  3. 2 the quick brown fox jumps over the lazy cat . dog
  4. 3 the quick brown fox jumps over the lazy cat . dog
  5. 4 the quick brown fox jumps over the lazy cat . dog
  6. 5 the quick brown fox jumps over the lazy cat . dog
  7. 打印test文本的行数
  8. [root@www ~]# awk 'END{print NR}' test
  9. 5
  10. 打印test文本最后一行内容
  11. [root@www ~]# awk 'END{print $0}' test
  12. 5 the quick brown fox jumps over the lazy cat . dog
  13. 打印test文本列数
  14. [root@www ~]# awk 'END{print NF}' test
  15. 12