shell概述

  • shell是一个程序,它连接了用户和Linux内核,它可以解释用户输入的命令传递给内核,让用户可以更加方便的使用Linux系统
  • shell 本身并不是内核的一部分,它只是站在内核基础上编写的一个应用程序
  • shell具备编程的能力,shell也是一种语言,C,C++,java,Python,Go等
  • 语言分为编译型语言,C,C++,Go,需要提前编译,编译语言都有编译器
  • 解释型语言,shell,Python,php,不需要提前编译,一边执行,一边编译,每种解释型语言都有解释器
  • shell语言支持大部分编程语言都具备的功能:if判断,for循环,变量,数组,函数,加减乘除,逻辑运算

规范shell脚本组成

  1. [root@test ~]# vim user.sh
  2. #!/bin/bash(环境声明)
  3. #注释信息
  4. 可执行代码…

如何写好一个shell脚本

  • 明确任务需求
  • 按需求整理好每一个步骤,先做什么,后做什么
  • 运行脚本,并根据运行结果排除错误
  • 优化脚本并达到最终效果

编写脚本

编写第一个脚本

  1. [root@localhost ~]# vim hello.sh
  2. #!/bin/bash
  3. #hello word
  4. echo hello word
  5. #赋予执行权限
  6. [root@localhost ~]# chmod u+x hello.sh
  7. #执行脚本
  8. [root@localhost ~]# /root/hello.sh
  9. hello word

编写创建用户脚本

  1. [root@localhost ~]# vim user.sh
  2. #!/bin/bash
  3. useradd abc
  4. passwd abc
  5. [root@localhost ~]# chmod u+x user.sh
  6. #非交互
  7. [root@localhost ~]# vim user.sh
  8. #!/bin/bash
  9. useradd yyyy
  10. echo 1 | passwd --stdin yyyy
  11. [root@localhost ~]# ./user.sh
  12. 更改用户 yyyy 的密码
  13. passwd:所有的身份验证令牌已经成功更新。

编写批量查看脚本

  1. #查看系统版本信息,查看系统内核信息,查看系统内存信息,查看系统网卡信息,查看当前主机名
  2. [root@localhost ~]# vim info.sh
  3. cat /etc/redhat-release
  4. uname -r
  5. free -h
  6. ifconfig ens32
  7. hostname
  8. #赋予执行权限
  9. [root@localhost ~]# chmod u+x info.sh
  10. #执行脚本
  11. [root@localhost ~]# ./info.sh
  12. CentOS Linux release 7.6.1810 (Core)
  13. 3.10.0-957.el7.x86_64
  14. total used free shared buff/cache available
  15. Mem: 972M 480M 147M 16M 344M 260M
  16. Swap: 2.0G 239M 1.8G
  17. ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  18. inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255
  19. inet6 fe80::8903:cb8:127b:dbc8 prefixlen 64 scopeid 0x20<link>
  20. ether 00:0c:29:a0:e8:12 txqueuelen 1000 (Ethernet)
  21. RX packets 230110 bytes 325471733 (310.3 MiB)
  22. RX errors 0 dropped 0 overruns 0 frame 0
  23. TX packets 20635 bytes 1385581 (1.3 MiB)
  24. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  25. localhost.localdomain

编写配置本地yum源脚本

  1. #编写搭建本地yum仓库脚本【版1,丢人版】
  2. [root@localhost ~]# vim yum.sh
  3. #!/bin/bash
  4. mkdir /mnt/centos
  5. mount /dev/cdrom /mnt/centos
  6. echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
  7. rm -rf /etc/yum.repos.d/*
  8. touch /etc/yum.repos.d/local.repo
  9. echo "[local]" > /etc/yum.repos.d/local.repo
  10. echo "name=local_centos" >> /etc/yum.repos.d/local.repo
  11. echo "baseurl=file:///mnt/centos" >> /etc/yum.repos.d/local.repo
  12. echo "enabled=1" >> /etc/yum.repos.d/local.repo
  13. echo "gpgcheck=0" >> /etc/yum.repos.d/local.repo
  14. #编写搭建本地yum仓库脚本【版2,正常版】
  15. [root@localhost ~]# vim yum.sh
  16. #!/bin/bash
  17. mkdir /mnt/centos
  18. mount /dev/cdrom /mnt/centos
  19. echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
  20. mount -a
  21. rm -rf /etc/yum.repos.d/*
  22. echo "[local]
  23. name=local_centos
  24. baseurl=file:///mnt/centos
  25. enabled=1
  26. gpgcheck=0" > /etc/yum.repos.d/local.repo
  27. #编写搭建本地yum仓库脚本【升级版】
  28. [root@localhost ~]# vim yum.sh
  29. #!/bin/bash
  30. echo "正在配置本地yum仓库..."
  31. mkdir /mnt/centos
  32. mount /dev/cdrom /mnt/centos &> /dev/null
  33. echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
  34. mount -a
  35. rm -rf /etc/yum.repos.d/*
  36. echo "[local]
  37. name=local_centos
  38. baseurl=file:///mnt/centos
  39. enabled=1
  40. gpgcheck=0" > /etc/yum.repos.d/local.repo
  41. echo "本地yum仓库配置以完成..."
  42. yum clean all &> /dev/null
  43. echo "仓库软件包数量"
  44. yum repolist | tail -1
  45. #执行脚本
  46. [root@localhost ~]# ./yum.sh
  47. 正在配置本地yum仓库...
  48. 本地yum仓库配置以完成...
  49. repolist: 4,021
  50. 仓库软件包数量

脚本的执行方式

  • 执行一个脚本的方法有很多种
  • 方法一:赋予脚本执行权限后,可用绝对路径或者当前路径执行
  • 方法二:调用解释器执行脚本文件
  1. #绝对路径执行脚本
  2. [root@localhost ~]# /root/hello.sh
  3. #相对路径执行脚本
  4. [root@localhost ~]# ./hello.sh
  5. #去除执行权限
  6. [root@localhost ~]# chmod u-x hello.sh
  7. #执行脚本
  8. [root@localhost ~]# /root/hello.sh
  9. -bash: /root/hello.sh: 权限不够
  10. [root@localhost ~]# ./hello.sh
  11. -bash: ./hello.sh: 权限不够
  12. #调用解释器执行脚本
  13. [root@localhost ~]# bash hello.sh
  14. hello word
  15. [root@localhost ~]# cat /etc/shells
  16. /bin/sh
  17. /bin/bash
  18. /usr/bin/sh
  19. /usr/bin/bash
  20. /bin/tcsh
  21. /bin/csh
  22. [root@localhost ~]# sh hello.sh
  23. hello word
  24. [root@localhost ~]# tcsh hello.sh
  25. hello word
  26. [root@localhost ~]# csh hello.sh
  27. hello word

常用特殊符号补充

  • “ “ #双引号,引用整体
  • ‘ ’ #单引号,引用整体并取消所有特殊字符含义
  • $[] #四则运算(+ - * / % 取余数)
  • $() #将命令的输出结果作为参数
  • #反撇 `` 将命令的输出结果作为参数
  1. #引用整体,不屏蔽特殊符号的功能
  2. [root@localhost ~]# echo "$PATH"
  3. /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
  4. #引用整体,屏蔽特殊符号的功能
  5. [root@localhost ~]# echo '$PATH'
  6. $PATH
  7. #没有特殊符号单引双引都可以
  8. [root@localhost ~]# echo "xxoo"
  9. xxoo
  10. [root@localhost ~]# echo 'xxoo'
  11. xxoo
  12. #四则运算
  13. [root@localhost ~]# echo $[1+1]
  14. 2
  15. [root@localhost ~]# echo $[1+5]
  16. 6
  17. [root@localhost ~]# echo $[10-5]
  18. 5
  19. [root@localhost ~]# echo $[10*5]
  20. 50
  21. [root@localhost ~]# echo $[10/5]
  22. 2
  23. [root@localhost ~]# echo $[1+3+4+5+7]
  24. 20
  25. [root@localhost ~]# echo $[10/3]
  26. 3
  27. [root@localhost ~]# echo $[10%3]
  28. 1
  29. #$()取命令结果作为参数
  30. root@localhost ~]# touch $(date +%F)-abc.txt
  31. 2021-05-09-abc.txt
  32. #``取命令结果作为参数
  33. [root@localhost ~]# touch `date +%F`-xxoo.txt
  34. 2021-05-09-xxoo.txt

变量

  • 以固定的名称存放可能变化的值,提高脚本的灵活度来适应多变的环境
  • 定义变量:变量名=变量值,如:a1=abc(等号两边不要有空格)
  • 取消变量:unset 变量名
  • 定义变量注意事项:
    • 变量名由字母/数字/下划线组成,区分大小写,不能以数字开头,不要使用命令和特殊符号
    • 若指定的变量名已经存在,相当于为此变量重新赋值
  1. root@localhost ~]# xx=haha
  2. [root@localhost ~]# echo $xx
  3. haha
  4. [root@localhost ~]# xx=abcd
  5. [root@localhost ~]# echo $xx
  6. abcd
  7. [root@localhost ~]# xx=5
  8. [root@localhost ~]# echo $xx
  9. 5
  10. [root@localhost ~]# echo $[xx+5]
  11. 10
  12. #通过变量定义用户名
  13. [root@localhost ~]# vim user.sh
  14. #!/bin/bash
  15. user=wangxin
  16. useradd $user
  17. echo 1 | passwd --stdin $user
  18. [root@localhost ~]# ./user.sh
  19. 更改用户 wangxin 的密码
  20. passwd:所有的身份验证令牌已经成功更新。
  21. [root@localhost ~]# vim user.sh
  22. #!/bin/bash
  23. user=sdd
  24. useradd $user
  25. echo 1 | passwd --stdin $user
  26. [root@localhost ~]# ./user.sh
  27. 更改用户 sdd 的密码
  28. passwd:所有的身份验证令牌已经成功更新。
  29. [root@localhost ~]# vim user.sh
  30. #!/bin/bash
  31. user=panghu
  32. useradd $user
  33. echo "用户$user创建成功"
  34. echo 1 | passwd --stdin $user &> /dev/null
  35. echo "用户$user密码设置成功"
  36. [root@localhost ~]# ./user.sh
  37. 用户panghu创建成功
  38. 用户panghu密码设置成功

read标准输入取值

  • read 读取用户在键盘上输入的内容,并把内容存放在变量里,可以降低脚本的使用难度
  • 命令格式:read -p “提示信息” 变量名
  1. [root@localhost ~]# vim user.sh
  2. #!/bin/bash
  3. read -p '请输入用户名:' user
  4. useradd $user
  5. echo "用户$user创建成功"
  6. read -p '请设置用户密码:' pass
  7. echo $pass | passwd --stdin $user &> /dev/null
  8. echo "用户$user密码设置成功"
  9. [root@localhost ~]# ./user.sh
  10. 请输入用户名:wuhan
  11. 用户wuhan创建成功
  12. 请设置用户密码:1
  13. 用户wuhan密码设置成功
  14. [root@localhost ~]# ./user.sh
  15. 请输入用户名:liangjing
  16. 用户liangjing创建成功
  17. 请设置用户密码:xxoo
  18. 用户liangjing密码设置成功

变量种类

  • 环境变量:变量名一般都大写,用来设置用户/系统环境
  • 位置变量:bash内置,存储执行脚本时提供的命令参数
  • 预定义变量:bash内置,可直接调用的特殊值,不能直接修改
  • 自定义变量:用户自定义
  • env 命令查看系统所有环境变量
  • set 命令查看系统所有变量,包括用户自定义变量
  • 环境变量
  1. [root@localhost etc]# env
  2. MAIL=/var/spool/mail/root
  3. PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
  4. PWD=/root
  5. LANG=zh_CN.UTF-8
  6. SELINUX_LEVEL_REQUESTED=
  7. HISTCONTROL=ignoredups
  8. SHLVL=1
  9. HOME=/root
  10. LOGNAME=root
  11. XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
  12. SSH_CONNECTION=192.168.0.1 51791 192.168.0.100 22
  13. LESSOPEN=||/usr/bin/lesspipe.sh %s
  14. XDG_RUNTIME_DIR=/run/user/0
  15. DISPLAY=localhost:10.0
  16. _=/usr/bin/env
  17. OLDPWD=/root
  18. #获取变量值
  19. [root@localhost etc]# echo $SHELL
  20. /bin/bash
  21. [root@localhost ~]# echo $PWD
  22. /root
  23. #查看系统所有变量
  24. [root@localhost ~]# set
  25. [root@localhost ~]# set | grep $a
  • 位置变量
    $0 #脚本名称
    $1 #第一个参数
    $2 #第二个参数
    $3 #第三个参数
    $4 #第四个参数
    $n… #第n个参数
  • 预定义变量
    $0 #代表脚本本身
    $* #显示所有参数内容
    $# #显示有多少个参数
    $? #显示上一条命令的执行结果(0代表正确,非0代表错误)
    1. [root@localhost ~]# vim test.sh
    2. #!/bin/bash
    3. echo $0
    4. echo $1
    5. echo $2
    6. echo $3
    7. echo $*
    8. echo $#
    9. echo $$
    10. echo $?
    11. #赋予执行权限,执行脚本
    12. [root@localhost ~]# ./test.sh xx oo dd
    13. ./test.sh $0
    14. xx $1
    15. oo $2
    16. dd $3
    17. xx oo dd $*
    18. 3 $#
    19. 15594 $$
    20. 0 $?

判断文件状态[ 参数 ]

  • -e #判断文档(文件/目录)是否存在,存在为真
  • -d #判断目录是否存在,存在为真
  • -f #判断文件是否存在,存在为真
  • -r #可读为真
  • -w #可写为真
  • -x #可执行为真
  1. #判断文档是否存在
  2. [root@localhost ~]# [ -e /etc/ ]
  3. [root@localhost ~]# echo $?
  4. 0 #为真
  5. #判断目录是否存在
  6. [root@localhost ~]# [ -d /opt ]
  7. [root@localhost ~]# echo $?
  8. 0
  9. [root@localhost ~]# [ -d /etc/passwd ]
  10. [root@localhost ~]# echo $?
  11. 1
  12. [root@localhost ~]# [ -f /etc/passwd ]
  13. [root@localhost ~]# echo $?
  14. 0
  15. #判断是否可读(以当前用户身份判断)
  16. [root@localhost ~]# [ -r /etc/passwd ]
  17. [root@localhost ~]# echo $?
  18. 0
  19. #判断是否可写
  20. [root@localhost ~]# [ -w /etc/passwd ]
  21. [root@localhost ~]# echo $?
  22. 0
  23. #判断是否可执行
  24. [root@localhost ~]# [ -x /etc/passwd ]
  25. [root@localhost ~]# echo $?
  26. 1
  27. [root@localhost ~]# ll /etc/passwd
  28. -rw-r--r--. 1 root root 3294 5 9 16:43 /etc/passwd

整数比较

  • -gt 大于
  • -ge 大于等于
  • -eq 等于
  • -lt 小于
  • -le 小于等于
  • -ne 不等于
  1. [root@localhost ~]# [ 1 -gt 1 ]
  2. [root@localhost ~]# echo $?
  3. 1
  4. [root@localhost ~]# [ 1 -eq 1 ]
  5. [root@localhost ~]# echo $?
  6. 0
  7. [root@localhost ~]# [ 1 -ge 1 ]
  8. [root@localhost ~]# echo $?
  9. 0
  10. [root@localhost ~]# [ 1 -ge 2 ]
  11. [root@localhost ~]# echo $?
  12. 1
  13. [root@localhost ~]# [ 1 -lt 2 ]
  14. [root@localhost ~]# echo $?
  15. 0
  16. [root@localhost ~]# [ 1 -le 2 ]
  17. [root@localhost ~]# echo $?
  18. 0
  19. [root@localhost ~]# [ 1 -le 10 ]
  20. [root@localhost ~]# echo $?
  21. 0
  22. [root@localhost ~]# [ 10 -le 10 ]
  23. [root@localhost ~]# echo $?
  24. 0
  25. [root@localhost ~]# [ 1 -ne 2 ]
  26. [root@localhost ~]# echo $?
  27. 0
  28. [root@localhost ~]# [ 2 -ne 2 ]
  29. [root@localhost ~]# echo $?
  30. 1

字符串对比

  • == 相等
  • != 不相等
  1. [root@localhost ~]# [ root == xxoo ]
  2. [root@localhost ~]# echo $?
  3. 1
  4. [root@localhost ~]# [ root == $USER ]
  5. [root@localhost ~]# echo $?
  6. 0
  7. [root@localhost ~]# [ $USER == root ]
  8. [root@localhost ~]# echo $?
  9. 0
  10. [root@localhost ~]# [ abc == bcd ]
  11. [root@localhost ~]# echo $?
  12. 1
  13. [root@localhost ~]# [ abc != bcd ]
  14. [root@localhost ~]# echo $?
  15. 0
  16. [root@localhost ~]# [ $USER != root ]
  17. [root@localhost ~]# echo $?
  18. 1

常用数值运算方式

  • $[] #四则运算(+ - * / % 取余数)
  • $(()) #数值运算工具
  • expr #数值运算工具
  • let #数值运算工具
  1. [root@localhost ~]# echo $[10+5]
  2. 15
  3. [root@localhost ~]# echo $[10-5]
  4. 5
  5. [root@localhost ~]# echo $[10*5]
  6. 50
  7. [root@localhost ~]# echo $[10/5]
  8. 2
  9. [root@localhost ~]# echo $[10%3]
  10. 1
  11. #$(())做数值运算
  12. [root@localhost ~]# echo $((10+5))
  13. 15
  14. [root@localhost ~]# echo $((10-5))
  15. 5
  16. [root@localhost ~]# echo $((10*5))
  17. 50
  18. [root@localhost ~]# echo $((10/5))
  19. 2
  20. [root@localhost ~]# echo $((10%3))
  21. 1
  22. #expr做数值运算
  23. [root@localhost ~]# echo expr 2+3
  24. expr 2+3
  25. [root@localhost ~]# echo `expr 2+3`
  26. 2+3
  27. #要求每一部分都要有空格
  28. [root@localhost ~]# echo `expr 2 + 3`
  29. 5
  30. [root@localhost ~]# echo `expr 10 - 3`
  31. 7
  32. #当进行乘法运算时,需要实用“\”转义掉*的特殊功能
  33. [root@localhost ~]# echo `expr 10 * 3`
  34. expr: 语法错误
  35. [root@localhost ~]# echo `expr 10 \* 3`
  36. 30
  37. [root@localhost ~]# echo `expr 10 / 3`
  38. 3
  39. #let做数值运算
  40. [root@localhost ~]# let 1+1
  41. #需要将运算的结果赋予一个变量存储
  42. [root@localhost ~]# let x=1+1
  43. [root@localhost ~]# echo $x
  44. 2
  45. [root@localhost ~]# let a=10+5
  46. [root@localhost ~]# echo $a
  47. 15
  48. #通过变量的值进行运算
  49. [root@localhost ~]# let b=a+x
  50. [root@localhost ~]# echo $b
  51. 17
  52. #let简写表达式 #let完整表达式
  53. let i++ let i=i+1
  54. [root@localhost ~]# i=10
  55. [root@localhost ~]# let i++
  56. [root@localhost ~]# echo $i
  57. 11
  58. let i-- let i=i-1
  59. [root@localhost ~]# let i--
  60. [root@localhost ~]# echo $i
  61. 10
  62. let i+=2 let i=i+2
  63. [root@localhost ~]# let i+=2
  64. [root@localhost ~]# echo $i
  65. 12
  66. let i-=2 let i=i-2
  67. [root@localhost ~]# let i-=2
  68. [root@localhost ~]# echo $i
  69. 10
  70. let i*=2 let i=i*2
  71. [root@localhost ~]# let i*=2
  72. [root@localhost ~]# echo $i
  73. 20
  74. let i/=2 let i=i/2
  75. [root@localhost ~]# let i/=2
  76. [root@localhost ~]# echo $i
  77. 10
  78. let i%=2 let i=1%2
  79. [root@localhost ~]# let i%=3
  80. [root@localhost ~]# echo $i
  81. 1

字符串判断

  • -z #字符串的值为空为真
  • -n #字符串的值非空为真(相当于 ! -z)
  1. #判断文件为空为真
  2. [root@localhost ~]# [-z /etc/passwd]
  3. bash: [-z: 未找到命令...
  4. #判断时每一部分要有空格
  5. [root@localhost ~]# [ -z /etc/passwd ]
  6. [root@localhost ~]# echo $?
  7. 1
  8. #判断文件非空为真
  9. [root@localhost ~]# [ -n /etc/passwd ]
  10. [root@localhost ~]# echo $?
  11. 0
  12. [root@localhost ~]# [ -z $i ]
  13. [root@localhost ~]# echo $?
  14. 1
  15. [root@localhost ~]# [ -n $i ]
  16. [root@localhost ~]# echo $?
  17. 0
  18. [root@localhost ~]# [ ! -z $i ]
  19. [root@localhost ~]# echo $?
  20. 0

条件判断结构

  • 当条件满足时执行什么操作,当条件不满足时执行什么操作
  • && #逻辑与(并且)
  • || #逻辑或(或者)
  • ; #条件之间没有逻辑关系
  1. A && B #当A命令执行成功后才会执行B,如果A执行失败则B不执行
  2. #判断存在且是文件执行拷贝操作(并且关系)
  3. [root@localhost ~]# [ -f /etc/passwd ] && cp /etc/passwd /opt
  4. [root@localhost ~]# ls /opt
  5. abc.tar.bz2 passwd
  6. #第一条命令执行失败,后边命令不执行
  7. [root@localhost ~]# [ -f /etc/xxoo ] && cp /etc/passwd /opt
  8. [root@localhost ~]# [ -f /etc/xxoo ] && cp /etc/xxoo /opt
  9. [root@localhost ~]# ls /opt
  10. A || B #当A命令执行失败后才会执行B,如果A执行成功则B不执行
  11. #前便命令执行失败,后边命令则执行
  12. [root@localhost ~]# [ -f /etc/xxoo ] || touch /opt/xxoo.txt
  13. [root@localhost ~]# ls /opt
  14. abc.tar.bz2 passwd xxoo.txt
  15. #前边命令执行成功,后便命令则不执行
  16. [root@localhost ~]# [ -f /etc/fstab ] || touch /opt/fs.txt
  17. [root@localhost ~]# ls /opt
  18. A ; B #执行A命令后执行B,两者没有逻辑关系
  19. [root@localhost ~]# touch /mnt/xx.txt ; touch /opt/xx.txt
  20. [root@localhost ~]# ls /mnt
  21. centos xx.txt
  22. [root@localhost ~]# ls /opt
  23. abc.tar.bz2 abc.txt fs.txt pass.txt passwd xxoo.txt xx.txt
  24. [root@localhost ~]# touch /opt/oo.txt ; rm -rf /opt/*
  25. [root@localhost ~]# ls /opt
  26. [root@localhost ~]# touch /opt/oo.txt ; rm -rf /opt/* ; touch /opt/xx.txt ; rm -rf /mnt/xx.txt
  27. [root@localhost ~]# ls /opt
  28. xx.txt
  29. [root@localhost ~]# ls /mnt/

if 条件判断结构

  • if 单分支语句,只能判断对,不能判断错
  1. #第一种语法结构
  2. if [条件判断];then
  3. 条件成立时,执行的命令
  4. fi
  5. #第二种语法结构
  6. if [条件判断]
  7. then
  8. 条件成立时,执行的命令
  9. fi
  10. #if单分支示例
  11. [root@localhost yunwei]# vim if1.sh
  12. #!/bin/bash
  13. if [ -n /etc/passwd ];then
  14. echo "非空"
  15. fi
  16. [root@localhost yunwei]# chmod u+x if1.sh
  17. [root@localhost yunwei]# ./if1.sh
  18. 非空
  19. #只能判断对,不能判断错
  20. [root@localhost yunwei]# vim if1.sh
  21. #!/bin/bash
  22. if [ -z /etc/passwd ];then
  23. echo "非空"
  24. fi

if 双分支语句

  1. if [条件判断];then
  2. 条件成立时,执行命令a
  3. else
  4. 条件不成立时,执行命令b
  5. fi
  6. #if双分支示例
  7. [root@localhost yunwei]# vim if2.sh
  8. #!/bin/bash
  9. if [ -z /etc/passwd ];then
  10. echo '空值'
  11. else
  12. echo '非空'
  13. fi
  14. [root@localhost yunwei]# chmod u+x if2.sh
  15. [root@localhost yunwei]# ./if2.sh
  16. 非空
  17. #编写参数字的脚本,让计算机产生一个0-9随机数
  18. #$RANDOM环境变量,里边存放的是0-65535之间的随机数
  19. [root@localhost yunwei]# echo $RANDOM
  20. 28484
  21. [root@localhost yunwei]# echo $RANDOM
  22. 5440
  23. [root@localhost yunwei]# echo $RANDOM
  24. 29651
  25. [root@localhost yunwei]# echo $RANDOM
  26. 21747
  27. [root@localhost yunwei]# echo $RANDOM
  28. 24494
  29. #实用$RANDOM的值对10取余
  30. [root@localhost yunwei]# echo $[RANDOM%10]
  31. 4
  32. [root@localhost yunwei]# echo $[RANDOM%10]
  33. 2
  34. [root@localhost yunwei]# echo $[RANDOM%10]
  35. 5
  36. [root@localhost yunwei]# echo $[RANDOM%10]
  37. 3
  38. [root@localhost yunwei]# echo $[RANDOM%10]
  39. 9
  40. [root@localhost yunwei]# echo $[RANDOM%10]
  41. 1
  42. [root@localhost yunwei]# echo $[RANDOM%10]
  43. 0
  44. [root@localhost yunwei]# echo $[RANDOM%10]
  45. 3
  46. [root@localhost yunwei]# echo $[RANDOM%10]
  47. 2
  48. #编写猜数字脚本
  49. [root@localhost yunwei]# vim if3.sh
  50. #!/bin/bash
  51. read -p '请输入0-9之间的随机数:' num
  52. num1=$[RANDOM%10]
  53. if [ $num -eq $num1 ];then
  54. echo "恭喜你才对了,奖励一个哇塞女孩!"
  55. else
  56. echo "猜错了,请继续努力,奖品是一个哇塞女孩!"
  57. echo "正确的结果为$num1"
  58. fi
  59. [root@localhost yunwei]# chmod u+x if3.sh
  60. root@localhost yunwei]# ./if3.sh
  61. 请输入0-9之间的随机数:1
  62. 猜错了,请继续努力,奖品是一个哇塞女孩!
  63. 正确的结果为6
  64. [root@localhost yunwei]# ./if3.sh
  65. 请输入0-9之间的随机数:7
  66. 猜错了,请继续努力,奖品是一个哇塞女孩!
  67. 正确的结果为3
  68. [root@localhost yunwei]# ./if3.sh
  69. 请输入0-9之间的随机数:3
  70. 猜错了,请继续努力,奖品是一个哇塞女孩!
  71. 正确的结果为2
  72. [root@localhost yunwei]# ./if3.sh
  73. 请输入0-9之间的随机数:0
  74. 猜错了,请继续努力,奖品是一个哇塞女孩!
  75. 正确的结果为5
  76. [root@localhost yunwei]# ./if3.sh
  77. 请输入0-9之间的随机数:9
  78. 猜错了,请继续努力,奖品是一个哇塞女孩!
  79. 正确的结果为2
  80. [root@localhost yunwei]# ./if3.sh
  81. 请输入0-9之间的随机数:5
  82. 猜错了,请继续努力,奖品是一个哇塞女孩!
  83. 正确的结果为7
  84. #安装软件包脚本
  85. root@localhost yunwei]# vim if4.sh
  86. #!/bin/bash
  87. if [ `rpm -q vsftpd &> /dev/null ; echo $?` -eq 0 ];then
  88. systemctl start vsftpd
  89. systemctl enable vsftpd &> /dev/null
  90. echo "软件包以安装,并设置随机自启"
  91. else
  92. yum -y install vsftpd &> /dev/null
  93. systemctl start vsftpd
  94. systemctl enable vsftpd &> /dev/null
  95. echo "软件包以重新安装上,并设置随机自启"
  96. fi
  97. [root@localhost yunwei]# chmod u+x if4.sh
  98. [root@localhost yunwei]# ./if4.sh
  99. 软件包以重新安装上,并设置随机自启

if 多分支语句

  1. if [条件判断1];then
  2. 条件1成立时,执行命令a
  3. elif [条件判断2];then
  4. 条件2成立时,执行命令b
  5. elif [条件判断3];then
  6. 条件3成立时,执行命令c
  7. ...省略更多条件
  8. else
  9. 所有条件都不成立时,执行命令d
  10. fi
  11. #编写判断成绩脚本
  12. [root@localhost yunwei]# vim if5.sh
  13. #!/bin/bash
  14. read -p "请输入你的成绩(满分为100分):" num
  15. if [ $num -ge 90 ];then
  16. echo "成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩"
  17. elif [ $num -ge 80 ];then
  18. echo "比较优秀"
  19. elif [ $num -ge 70 ];then
  20. echo "一般一般"
  21. elif [ $num -ge 60 ];then
  22. echo "勉强及格"
  23. else
  24. echo "收拾收拾,回家种地去吧!"
  25. fi
  26. [root@localhost yunwei]# chmod u+x if5.sh
  27. [root@localhost yunwei]# ./if5.sh
  28. 请输入你的成绩:66
  29. 勉强及格
  30. [root@localhost yunwei]# ./if5.sh
  31. 请输入你的成绩:55
  32. 收拾收拾,回家种地去吧!
  33. [root@localhost yunwei]# ./if5.sh
  34. 请输入你的成绩:0
  35. 收拾收拾,回家种地去吧!
  36. [root@localhost yunwei]# ./if5.sh
  37. 请输入你的成绩:99
  38. 成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
  39. [root@localhost yunwei]# vim if5.sh
  40. [root@localhost yunwei]# ./if5.sh
  41. 请输入你的成绩(满分为100分):100
  42. 成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
  43. [root@localhost yunwei]# ./if5.sh
  44. 请输入你的成绩(满分为100分):90
  45. 成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
  46. [root@localhost yunwei]# ./if5.sh
  47. 请输入你的成绩(满分为100分):200
  48. 成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩

case条件判断结构

  • case从变量中取值,如果变量中的值与预设的值匹配,则执行对应的命令
  1. #case语法结构
  2. case $变量名 in
  3. 1)
  4. 执行的命令xx;; #如果变量中的值等于值1,则执行的命令
  5. 2)
  6. 执行的命令yy;; #如果变量中的值等于2,则执行的命令
  7. ...省略其他分支
  8. *)
  9. 执行的命令zz;; #如果变量中的值都不是以上的值,则执行的命令
  10. esac
  11. [root@localhost yunwei]# vim case.sh
  12. #!/bin/bash
  13. read -p "请输入您喜爱的老师(仓老师|波多老师|小泽老师):" xxoo
  14. case $xxoo in
  15. 仓老师)
  16. echo "又白又嫩又水润,上楼右转1号房间!";;
  17. 波多老师)
  18. echo "前凸后翘,波涛汹涌,上楼右转2号房间!";;
  19. 小泽老师)
  20. echo "肤白貌美大长腿,上楼右转3号房间!";;
  21. *)
  22. echo "老师休假了";;
  23. esac
  24. [root@localhost yunwei]# chmod u+x case.sh
  25. [root@localhost yunwei]# ./case.sh
  26. 请输入您喜爱的老师(仓老师|波多老师|小泽老师):仓老师
  27. 又白又嫩又水润,上楼右转1号房间!
  28. [root@localhost yunwei]# ./case.sh 波多老师
  29. 请输入您喜爱的老师(仓老师|波多老师|小泽老师):波多老师
  30. 前凸后翘,波涛汹涌,上楼右转2号房间!
  31. [root@localhost yunwei]# ./case.sh
  32. 请输入您喜爱的老师(仓老师|波多老师|小泽老师):小泽老师
  33. 肤白貌美大长腿,上楼右转3号房间!
  34. [root@localhost yunwei]# ./case.sh
  35. 请输入您喜爱的老师(仓老师|波多老师|小泽老师):穆穆老师
  36. 老师休假了

for循环

  • for循环处理,根据变量的取值,重复执行xx命令
  1. #for循环语法结构
  2. for 变量名 in 1 2 3 N...
  3. do
  4. 执行的命令
  5. done
  6. #编写循环创建用户脚本
  7. [root@localhost yunwei]# vim user.sh
  8. #!/bin/bash
  9. for user in xiaofang xiaowei jiumei alian
  10. do
  11. useradd $user
  12. echo "$user 创建成功"
  13. echo 1 | passwd --stdin $user &> /dev/null
  14. echo "$user 密码设置成功,初始密码为“1”"
  15. done
  16. [root@localhost yunwei]# chmod u+x user.sh
  17. [root@localhost yunwei]# ./user.sh
  18. useradd:用户“xiaofang”已存在
  19. xiaofang 创建成功
  20. xiaofang 密码设置成功,初始密码为“1
  21. xiaowei 创建成功
  22. xiaowei 密码设置成功,初始密码为“1
  23. jiumei 创建成功
  24. jiumei 密码设置成功,初始密码为“1
  25. alian 创建成功
  26. alian 密码设置成功,初始密码为“1
  27. #测试企业的服务器联通性
  28. #!/bin/bash
  29. for i in `seq 254`
  30. do
  31. ping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null #-c ping几次 -i ping延迟时间 -w ping超时时间
  32. if [ $? -eq 0 ];then
  33. echo "192.168.0.$i UP"
  34. else
  35. echo "192.168.0.$i DOWN"
  36. fi
  37. done
  38. [root@localhost yunwei]# chmod u+x ping.sh
  39. [root@localhost yunwei]# ./ping.sh
  40. #问题:如何将ping的命令结果存储到文件当中,正确的输出结果与错误的输出结果分别单独存储
  41. #!/bin/bash
  42. echo "请耐心等待!正在进行ping测试!"
  43. for i in `seq 4`
  44. do
  45. ping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null #-c ping几>次 -i ping延迟时间 -w ping超时时间
  46. if [ $? -eq 0 ];then
  47. echo "192.168.0.$i UP" &>> /opt/ping_up.txt
  48. else
  49. echo "192.168.0.$i DOWN" &>> /opt/ping_done.txt
  50. fi
  51. done
  52. echo "记录完成!"

while循环

  • 死循环,只要条件成立就重复执行命令
  1. #while循环语法结构
  2. while 条件判断
  3. do
  4. 执行的命令
  5. done
  6. #编写while循环脚本
  7. [root@localhost yunwei]# vim while.sh
  8. #!/bin/bash
  9. a=1
  10. while [ $a -le 5 ]
  11. do
  12. echo $a
  13. done
  14. [root@localhost yunwei]# chmod u+x while.sh
  15. #指定循环的固定次数
  16. [root@localhost yunwei]# vim while.sh
  17. #!/bin/bash
  18. a=1
  19. while [ $a -le 5 ]
  20. do
  21. echo $a
  22. let a++
  23. sleep 0.1
  24. done
  25. #使用while循环编写猜数字脚本
  26. [root@localhost yunwei]# vim while1.sh
  27. #!/bin/bash
  28. num=$[RANDOM%10]
  29. while :
  30. do
  31. read -p "请输入0-10之间的数字:" num1
  32. if [ $num -eq $num1 ];then
  33. echo "恭喜你才对了,奖励一个绝世容颜哇塞女孩!"
  34. exit #退出脚本
  35. else
  36. echo "请继续努力,离哇塞女孩还差一步了,加油!"
  37. fi
  38. done
  39. #利用while循环监控网卡进出口流量
  40. [root@localhost ~]# vim net_ens32.sh
  41. #!/bin/bash
  42. while :
  43. do
  44. clear #清屏
  45. ifconfig ens32 | head -2 #显示网卡头两行信息
  46. ifconfig ens32 | grep "RX p" #网卡入口流量
  47. ifconfig ens32 | grep "TX p" #网卡出口流量
  48. sleep 0.2 #休眠0.2秒
  49. done
  50. #使用while循环编写一个测试整个网段IP地址的联通性脚本
  51. #!/bin/bash
  52. echo "请耐心等待,正在进行ping测试!"
  53. i=1
  54. while [ $i -le 4 ]
  55. do
  56. ping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null
  57. if [ $? -eq 0 ];then
  58. echo "192.168.0.$i UP" &>> /opt/ping_up.txt
  59. else
  60. echo "192.168.0.$i DOWN" &>> /opt/ping_done.txt
  61. fi
  62. let i++
  63. done
  64. echo "记录完成!"
  65. ~

shell函数

  • 在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可称为函数(给一堆命令取一个别名)
  • 函数可以使脚本中的代码更加简洁,增强易读性,提高脚本的执行效率
  1. #函数定义格式1
  2. function 函数名 {
  3. 执行的命令1
  4. 执行的命令2
  5. ...省略更多命令
  6. }
  7. #函数定义格式2
  8. 函数名() {
  9. 执行的命令1
  10. 执行的命令2
  11. ...省略更多命令
  12. }
  13. #定义函数
  14. [root@localhost ~]# net_ens32() {
  15. > ifconfig ens32 | head -2
  16. > ifconfig ens32 | grep "RX p"
  17. > ifconfig ens32 | grep "TX p"
  18. > }
  19. #调用函数
  20. [root@localhost ~]# net_ens32
  21. ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  22. inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255
  23. RX packets 2337 bytes 178268 (174.0 KiB)
  24. TX packets 2686 bytes 467232 (456.2 KiB)
  25. #定义函数
  26. [root@localhost ~]# myinfo() {
  27. > hostname # 用户名
  28. > cat /etc/redhat-release # Linux版本
  29. > uname -r #内核版本
  30. > free -h # 查看内存使用情况
  31. > df -h / #查看分区的使用情况
  32. > }
  33. #调用函数
  34. [root@localhost ~]# myinfo
  35. localhost
  36. CentOS Linux release 7.6.1810 (Core)
  37. 3.10.0-957.el7.x86_64
  38. total used free shared buff/cache available
  39. Mem: 972M 393M 193M 13M 385M 374M
  40. Swap: 2.0G 0B 2.0G
  41. 文件系统 容量 已用 可用 已用% 挂载点
  42. /dev/mapper/centos-root 56G 5.2G 51G 10% /
  43. #fork炸弹
  44. [root@localhost yunwei]# vim fork.sh
  45. #!/bin/bash
  46. .() {
  47. .|. &
  48. }
  49. .
  50. [root@localhost yunwei]# chmod u+x fork.sh
  51. [root@localhost yunwei]# ./fork.sh

脚本中断及退出

  • break #结束整个循环
  • continue #结束本次循环,进入下一次循环
  • exit #退出脚本
  1. #结束第三次循环,进入下一次循环
  2. #!/bin/bash
  3. for i in {1..5}
  4. do
  5. [ $i -eq 3 ] && continue
  6. echo $i
  7. done
  8. echo Over
  9. [root@localhost yunwei]# ./for1.sh
  10. 1
  11. 2
  12. 4
  13. 5
  14. Over
  15. #结束整个循环
  16. #!/bin/bash
  17. for i in {1..5}
  18. do
  19. [ $i -eq 3 ] && break
  20. echo $i
  21. done
  22. echo Over
  23. [root@localhost yunwei]# ./for1.sh
  24. 1
  25. 2
  26. Over
  27. #直接退出脚本
  28. [root@localhost yunwei]# vim for1.sh
  29. #!/bin/bash
  30. for i in {1..5}
  31. do
  32. [ $i -eq 3 ] && exit
  33. echo $i
  34. done
  35. echo Over
  36. [root@localhost yunwei]# ./for1.sh
  37. 1
  38. 2

字符串截取

  • 在使用shell脚本完成各种运维任务时,一旦涉及到判断、条件测试等相关操作时往往需要对相关的命令输出进行过滤,提取出符合要求的字符串
  • 字符串截取的常用方法:${变量名:起始位置:长度}
  • ${}截取字符串时,起始位置是从0开始的
  1. [root@localhost yunwei]# phone=13812345678
  2. [root@localhost yunwei]# echo $phone
  3. 13812345678
  4. #统计变量的个数
  5. [root@localhost yunwei]# echo ${#phone}
  6. 11
  7. #截取变量的前三位,在截取时包含数字本身:13812345678
  8. [root@localhost yunwei]# echo ${phone:0:3}
  9. 138
  10. #截取后四位
  11. [root@localhost yunwei]# echo ${phone:7:4}
  12. 5678
  13. #截取中间四位
  14. [root@localhost yunwei]# echo ${phone:3:4}
  15. 1234
  16. #截取一个随机的8位密码
  17. [root@localhost yunwei]# vim mima.sh
  18. #!/bin/bash
  19. x=qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789
  20. for i in {1..8}
  21. do
  22. n=$[RANDOM%62]
  23. p=${x:n:1}
  24. pass=$pass$p
  25. done
  26. echo $pass
  27. [root@localhost yunwei]# ./mima.sh
  28. 42iVW9Ba
  29. [root@localhost yunwei]# ./mima.sh
  30. XuEcVGoR

字符串替换

  • 只替换第一个匹配的结果:${变量名/xx/yy}
  • 替换全部匹配的结果:${变量名//xx/yy}
  1. #只替换匹配到的第一个字符
  2. [root@localhost yunwei]# echo $phone
  3. 13812345678
  4. #将匹配到的第一个3替换成4
  5. [root@localhost yunwei]# echo ${phone/3/4}
  6. 14812345678
  7. #将匹配到的所有3替换成4
  8. [root@localhost yunwei]# echo ${phone//3/4}
  9. 14812445678

字符串掐头去尾

  • 从左向右,最短匹配删除:${变量名#*关键词}
  • 从左向右,最长匹配删除:${变量名##*关键词}
  • 从右向左,最短匹配删除:${变量名%关键词*}
  • 从右向左,最长匹配删除:${变量名%%关键词*}
  1. #定义素材
  2. [root@localhost yunwei]# x=`head -1 /etc/passwd`
  3. [root@localhost yunwei]# echo $x
  4. root:x:0:0:root:/root:/bin/bash
  5. #从左到右最短匹配
  6. [root@localhost yunwei]# echo ${x#root}
  7. :x:0:0:root:/root:/bin/bash
  8. #从左到右最短匹配,不加*只匹配最左侧的字串
  9. [root@localhost yunwei]# echo ${x#0}
  10. root:x:0:0:root:/root:/bin/bash
  11. #从左到右最短匹配,加*匹配遇到的第一个字串
  12. [root@localhost yunwei]# echo ${x#*0}
  13. :0:root:/root:/bin/bash
  14. #从左到右最长匹配
  15. [root@localhost yunwei]# echo ${x##0}
  16. root:x:0:0:root:/root:/bin/bash
  17. #从左到右最长匹配
  18. [root@localhost yunwei]# echo ${x##*0}
  19. :root:/root:/bin/bash
  20. #从右到做最短匹配
  21. [root@localhost yunwei]# echo ${x%/bash}
  22. root:x:0:0:root:/root:/bin
  23. #从右到做最短匹配
  24. [root@localhost yunwei]# echo ${x%root*}
  25. root:x:0:0:root:/
  26. #从右向左最长匹配
  27. [root@localhost yunwei]# echo ${x%%root*}
  28. #从右向左最短匹配
  29. [root@localhost yunwei]# echo ${x%0*}
  30. root:x:0:
  31. #从右向左最长匹配
  32. [root@localhost yunwei]# echo ${x%%0*}
  33. root:x:
  34. #把文件以.doc结尾的扩展名,全部改为.txt
  35. [root@localhost yunwei]# touch {1..100}.doc
  36. [root@localhost yunwei]# ls
  37. 100.doc 17.doc 24.doc 31.doc 39.doc 46.doc 53.doc 60.doc 68.doc 75.doc 82.doc 8.doc 97.doc if2.sh while.sh
  38. 10.doc 18.doc 25.doc 32.doc 3.doc 47.doc 54.doc 61.doc 69.doc 76.doc 83.doc 90.doc 98.doc if3.sh
  39. 11.doc 19.doc 26.doc 33.doc 40.doc 48.doc 55.doc 62.doc 6.doc 77.doc 84.doc 91.doc 99.doc if4.sh
  40. 12.doc 1.doc 27.doc 34.doc 41.doc 49.doc 56.doc 63.doc 70.doc 78.doc 85.doc 92.doc 9.doc if5.sh
  41. 13.doc 20.doc 28.doc 35.doc 42.doc 4.doc 57.doc 64.doc 71.doc 79.doc 86.doc 93.doc case.sh mima.sh
  42. 14.doc 21.doc 29.doc 36.doc 43.doc 50.doc 58.doc 65.doc 72.doc 7.doc 87.doc 94.doc for1.sh ping.sh
  43. 15.doc 22.doc 2.doc 37.doc 44.doc 51.doc 59.doc 66.doc 73.doc 80.doc 88.doc 95.doc fork.sh user.sh
  44. 16.doc 23.doc 30.doc 38.doc 45.doc 52.doc 5.doc 67.doc 74.doc 81.doc 89.doc 96.doc if1.sh while1.sh
  45. #字符串去尾方式批量修改文件扩展名
  46. [root@localhost yunwei]# vim file.sh
  47. #!/bin/bash
  48. for i in `ls *.doc`
  49. do
  50. mv $i ${i%doc}txt
  51. done
  52. #字符串替换方式批修改文件扩展名
  53. [root@localhost yunwei]# vim file.sh
  54. #!/bin/bash
  55. for i in `ls *.txt`
  56. do
  57. mv $i ${i/txt/doc}
  58. done

shell数组

  1. #定义数组方式一:数组名=(值1 值2 值3 .. .. 值n)
  2. [root@localhost yunwei]# x=(11 22 33 44 55 abc)
  3. [root@localhost yunwei]# echo $x
  4. 11
  5. #按照下标取值,下标从0起使,0就是数据内的第一个值
  6. [root@localhost yunwei]# echo ${x[0]}
  7. 11
  8. [root@localhost yunwei]# echo ${x[0]}
  9. 11
  10. [root@localhost yunwei]# echo ${x[1]}
  11. 22
  12. [root@localhost yunwei]# echo ${x[2]}
  13. 33
  14. [root@localhost yunwei]# echo ${x[3]}
  15. 44
  16. [root@localhost yunwei]# echo ${x[4]}
  17. 55
  18. #获取数组内所有值
  19. [root@localhost yunwei]# echo ${x[@]}
  20. 11 22 33 44 55 abc
  21. #定义数组方式二:数组名[下标]=值
  22. [root@localhost yunwei]# b[0]=aa
  23. [root@localhost yunwei]# b[1]=xx
  24. [root@localhost yunwei]# b[2]=xxoo
  25. [root@localhost yunwei]# echo ${b[0]}
  26. aa
  27. [root@localhost yunwei]# echo ${b[1]}
  28. xx
  29. [root@localhost yunwei]# echo ${b[2]}
  30. xxoo
  31. [root@localhost yunwei]# echo ${b[@]}
  32. aa xx xxoo
  33. [root@localhost yunwei]# echo ${b[*]}
  34. aa xx xxoo

正则表达式

  • 正则表达式使用一串符号描述有共同属性的数据 | 基本正则符号 | 描述 | | —- | —- | | ^ | 匹配行首 | | $ | 匹配行尾 | | [] | 集合,匹配集合中的任意单个字符 | | [^] | 对集合取反 | | . | 匹配任意单个字符 | | * | 匹配前一个字符出现的任意次数[*不允许单独[使用] | | {n,m} | 匹配前一个字符 n 到 m 次 | | {n} | 匹配前一个字符 n 次 |
  1. #匹配以什么什么开头的行
  2. [root@localhost yunwei]# grep "^root" /etc/passwd
  3. root:x:0:0:root:/root:/bin/bash
  4. [root@localhost yunwei]# grep "^#" /etc/fstab
  5. #匹配以什么什么结尾的行
  6. [root@localhost yunwei]# grep "bash$" /etc/passwd
  7. [root@localhost yunwei]# grep -v "^#" /etc/fstab
  8. [root@localhost yunwei]# grep -v "^#" /etc/fstab | grep -v "^$"
  9. #集合,匹配集合中的任意单个字符
  10. [root@localhost yunwei]# grep "ro[abcotabcd]" /etc/passwd
  11. #集合,对集合中的任意单个字符取反
  12. [root@localhost yunwei]# grep "ro[^abcotabcd]" /etc/passwd
  13. #匹配任意单个字符
  14. [root@localhost yunwei]# grep "roo." /etc/passwd
  15. [root@localhost yunwei]# grep ".oot" /etc/passwd
  16. [root@localhost yunwei]# grep "w.*" /etc/passwd
  17. #准备素材
  18. [root@localhost yunwei]# vim 1.txt
  19. a
  20. b
  21. ab
  22. aab
  23. acb
  24. adb
  25. amnb
  26. amnbmnbmnb
  27. aaaabaaaaaaabaaaaaaaaaaaaab
  28. aabb the ccdd
  29. abcthe
  30. thexxoo
  31. xxootheooxx
  32. [root@localhost yunwei]# grep "a*b" 1.txt
  33. [root@localhost yunwei]# grep "a.*b" 1.txt #任意所有
  34. [root@localhost yunwei]# grep ".*b" 1.txt
  35. [root@localhost yunwei]# grep "a.*" 1.txt
  36. #匹配前一个字符至少出现一次以上,\{n,m\}
  37. [root@localhost yunwei]# grep "a\{1,\}" 1.txt
  38. #匹配前一个字符 n 次,\{n\}
  39. [root@localhost yunwei]# grep "o\{2\}" /etc/passwd
  40. [root@localhost yunwei]# grep "a\{2\}" 1.txt
扩展正则符号 描述
+ 最少匹配一次
最多匹配一次
{n,m} 匹配 n 到 m 次
() 组合为整体,保留(复制)
| 或者
\b 单词边界
  1. #基本正则用法
  2. [root@localhost yunwei]# grep "a\{2,4\}b" 1.txt
  3. #使用扩展正则时,需要使用egrep命令过滤
  4. [root@localhost yunwei]# egrep "a{2,4}b" 1.txt
  5. #匹配前一个字符至少出现一次以上
  6. [root@localhost yunwei]# egrep "a+" 1.txt
  7. #基本正则实现方式,匹配前一个字符至少出现一次以上
  8. [root@localhost yunwei]# grep "a\{1,\}" 1.txt
  9. #匹配前一个字符出现了0次或一次
  10. [root@localhost yunwei]# egrep "a?b" 1.txt
  11. #基本正则实现方式,匹配前一个字符出现了0次或一次
  12. [root@localhost yunwei]# grep "a\{0,1\}b" 1.txt
  13. #或者
  14. [root@localhost yunwei]# egrep "ab|acb|aaab" 1.txt
  15. #组合为整体
  16. [root@localhost yunwei]# egrep "(ab)" 1.txt
  17. ab
  18. aab
  19. aaaabaaaaaaabaaaaaaaaaaaaab
  20. [root@localhost yunwei]# egrep "(acb)" 1.txt
  21. acb
  22. [root@localhost yunwei]# egrep "(aaab)" 1.txt
  23. #单词边界
  24. [root@localhost yunwei]# grep "the" 1.txt
  25. aabb the ccdd
  26. abcthe
  27. thexxoo
  28. xxootheooxx
  29. [root@localhost yunwei]# egrep "\bthe\b" 1.txt
  30. aabb the ccdd
  31. [root@localhost yunwei]# egrep "\bthe" 1.txt
  32. aabb the ccdd
  33. thexxoo
  34. [root@localhost yunwei]# egrep "the\b" 1.txt
  35. aabb the ccdd
  36. abcthe

sed流式编辑器

  • sed是一个非交互的文本编辑器,实现的功能跟vim相同,主要是对文件内容进行输出、删除、替换、复制、剪切、导入、导出等功能
  • 命令格式1:前置命令 | sed [选项] ‘[指令]’ 文件名
  • 命令格式2:sed [选项] ‘[指令]’ 文件名
  • 常用选项:
    • -n #屏蔽默认输出,默认sed会将所有的输出结果输出到屏幕中,-n只把sed处理的行输出到屏幕
    • -i #直接修改文件内容,如果不加-i选项,并不会真正改变文件的内容
    • -r #使用扩展正则,若与其他选项连用应作为首个选项
  • 动作指令:
    • p #打印指定的行,如:2,4p 打印第234行,如:2p;4p 打印第2行与第4行
    • d #删除指定的行,如:2,4d 删除第234行
    • s #字符串替换,如:s/旧字串/新字串/
    • r #导入文件内容,如:4r 1.txt 在第4行下导入1.txt文件内容
    • w #导出文件内容,如:3w 1.txt 将文件第三行内容另存到2.txt文件中
  1. #打印文件第一行内容
  2. [root@localhost yunwei]# sed -n '1p' /etc/passwd
  3. root:x:0:0:root:/root:/bin/bash
  4. #打印文件第三行内容
  5. [root@localhost yunwei]# sed -n '3p' /etc/passwd
  6. daemon:x:2:2:daemon:/sbin:/sbin/nologin
  7. #打印文件第3行到6行
  8. [root@localhost yunwei]# sed -n '3,6p' /etc/passwd
  9. daemon:x:2:2:daemon:/sbin:/sbin/nologin
  10. adm:x:3:4:adm:/var/adm:/sbin/nologin
  11. lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
  12. sync:x:5:0:sync:/sbin:/bin/sync
  13. #打印文件第3行到6行
  14. [root@localhost yunwei]# head -6 /etc/passwd | tail -4
  15. daemon:x:2:2:daemon:/sbin:/sbin/nologin
  16. adm:x:3:4:adm:/var/adm:/sbin/nologin
  17. lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
  18. sync:x:5:0:sync:/sbin:/bin/sync
  19. #利用正则表达式匹配以root开头的行(正则表达式要放在//内)
  20. [root@localhost yunwei]# sed -n '/^root/p' /etc/passwd
  21. #匹配以bash结尾的行
  22. [root@localhost yunwei]# sed -n '/bash$/p' /etc/passwd
  23. [root@localhost yunwei]# sed -n '/nologin$/p' /etc/passwd
  24. #打印文件最后一行,打印行号
  25. [root@localhost yunwei]# sed -n '$=' /etc/passwd
  26. 70
  27. [root@localhost yunwei]# sed -n '/^root/=' /etc/passwd
  28. 1
  29. #拷贝文件练习
  30. [root@localhost opt]# cp /etc/passwd /opt/test
  31. #删除文件2到4行
  32. [root@localhost opt]# sed '2,4d' test | wc -l
  33. 67
  34. #使用i选项直接修改源文件
  35. [root@localhost opt]# sed -i '2,4d' test
  36. #使用分号分隔
  37. [root@localhost opt]# sed -i '10d;12d' test
  38. [root@localhost opt]# sed -n '$=' test
  39. 62
  40. #制作素材
  41. [root@localhost opt]# vim 1.txt
  42. aaaabbbbb
  43. bbbbbaaaa
  44. cccccaaaaa
  45. dddddaaaa
  46. [root@localhost opt]# sed -n '/aaaa/p' 1.txt
  47. aaaabbbbb
  48. bbbbbaaaa
  49. cccccaaaaa
  50. dddddaaaa
  51. #取反删除
  52. [root@localhost opt]# sed -i '/cccc/!d' 1.txt
  53. [root@localhost opt]# cat 1.txt
  54. ccccaaaa
  55. [root@localhost opt]# vim 1.txt
  56. aaaabbbb
  57. ddddaaaa
  58. zzzzaaaa
  59. ccccaaaa
  60. #删除以ccc开头的行
  61. [root@localhost opt]# sed -i '/^cccc/d' 1.txt
  62. [root@localhost opt]# cat 1.txt
  63. aaaabbbb
  64. ddddaaaa
  65. zzzzaaaa
  66. #删除空行
  67. [root@localhost opt]# sed -i '/^$/d' 1.txt
  68. [root@localhost opt]# cat 1.txt
  69. #准备素材
  70. [root@localhost opt]# vim xx.txt
  71. 2021 2020 2019 2018
  72. 2021 2021 2020 2019
  73. 2021 2022 2021 2020
  74. #替换文件每一行匹配到的第一个字串
  75. [root@localhost opt]# sed 's/2021/xxxx/' xx.txt
  76. xxxx 2020 2019 2018
  77. xxxx 2021 2020 2019
  78. xxxx 2022 2021 2020
  79. #替换文件每一行匹配到的第二个字串
  80. [root@localhost opt]# sed 's/2021/xxxx/2' xx.txt
  81. 2021 2020 2019 2018
  82. 2021 xxxx 2020 2019
  83. 2021 2022 xxxx 2020
  84. #替换文件每一行匹配到的所有指定字串
  85. [root@localhost opt]# sed 's/2021/xxxx/g' xx.txt
  86. xxxx 2020 2019 2018
  87. xxxx xxxx 2020 2019
  88. xxxx 2022 xxxx 2020
  89. #将匹配到的第一个字串替换成空
  90. [root@localhost opt]# sed 's/2021//' xx.txt
  91. 2020 2019 2018
  92. 2021 2020 2019
  93. 2022 2021 2020
  94. #将匹配到的第=二字串替换成空
  95. [root@localhost opt]# sed 's/2021//2' xx.txt
  96. 2021 2020 2019 2018
  97. 2021 2020 2019
  98. 2021 2022 2020
  99. #替换时屏蔽默认输出
  100. [root@localhost opt]# sed -n 's/root/xxoo/g' test
  101. [root@localhost opt]# sed -n 's/root/xxoo/gp' test
  102. xxoo:x:0:0:xxoo:/xxoo:/bin/bash
  103. operator:x:11:0:operator:/xxoo:/sbin/nologin
  104. #替换符可以使用任意的特殊符号
  105. [root@localhost opt]# sed 's#2021#xxoo#' xx.txt
  106. xxoo 2020 2019 2018
  107. xxoo 2021 2020 2019
  108. xxoo 2022 2021 2020
  109. [root@localhost opt]# sed 's,2021,xxoo,' xx.txt
  110. xxoo 2020 2019 2018
  111. xxoo 2021 2020 2019
  112. xxoo 2022 2021 2020
  113. [root@localhost opt]# sed 's!2021!xxoo!' xx.txt
  114. xxoo 2020 2019 2018
  115. xxoo 2021 2020 2019
  116. xxoo 2022 2021 2020
  117. [root@localhost opt]# sed 's;2021;xxoo;' xx.txt
  118. xxoo 2020 2019 2018
  119. xxoo 2021 2020 2019
  120. xxoo 2022 2021 2020
  121. [root@localhost opt]# sed 's*2021*xxoo*' xx.txt
  122. xxoo 2020 2019 2018
  123. xxoo 2021 2020 2019
  124. xxoo 2022 2021 2020
  125. [root@localhost opt]# sed 's:2021:xxoo:' xx.txt
  126. xxoo 2020 2019 2018
  127. xxoo 2021 2020 2019
  128. xxoo 2022 2021 2020
  129. #将文件中/bin/bash替换成/bin/sh
  130. [root@localhost opt]# sed -n 's/\/bin\/bash/\/bin\/sh/gp' test
  131. [root@localhost opt]# sed -n 's,/bin/bash,/bin/sh,gp' test
  132. #使用sed给文件1-7行批量添加注释
  133. [root@localhost opt]# sed -n '1,7s/^/#/p' test
  134. #使用sed给文件1-7行批量添加注释,直接修改源文件
  135. [root@localhost opt]# sed -i '1,7s/^/#/p' test
  136. #批量去除1-7行的注释
  137. [root@localhost opt]# sed -n '1,7s/^#//p' test
  138. #批量去除1-7行的注释,直接修改源文件
  139. [root@localhost opt]# sed -i '1,7s/^#//p' test
  140. #将文件中所有的数字替换成空
  141. [root@localhost opt]# sed -n 's/[0-9]//gp' test
  142. #将文件中所有的英文字母替换成空
  143. [root@localhost opt]# sed -n 's/[a-Z]//gp' test
  144. #准备素材
  145. [root@localhost opt]# vim a.txt
  146. xxxxxxx
  147. yyyyyyy
  148. zzzzzz
  149. #将a.txt文件内容导入到test文件中,默认读一行导一遍
  150. [root@localhost opt]# sed 'r/opt/a.txt' test
  151. #指定导入的行,导入到test文件第一行下边
  152. [root@localhost opt]# sed '1r/opt/a.txt' test
  153. root:x:0:0:root:/root:/bin/bash
  154. xxxxxxx
  155. yyyyyyy
  156. zzzzzz
  157. #指定连续导入的行
  158. [root@localhost opt]# sed '1,3r/opt/a.txt' test
  159. root:x:0:0:root:/root:/bin/bash
  160. xxxxxxx
  161. yyyyyyy
  162. zzzzzz
  163. root:x:0:0:root:/root:/bin/bash
  164. xxxxxxx
  165. yyyyyyy
  166. zzzzzz
  167. root:x:0:0:root:/root:/bin/bash
  168. xxxxxxx
  169. yyyyyyy
  170. zzzzzz
  171. #将a.txt文件第一行内容导出到b.txt文件中
  172. [root@localhost opt]# sed '1w b.txt' a.txt
  173. [root@localhost opt]# cat b.txt
  174. xxxxxxx

awk编程语言

  • awk编程语言/数据处理引擎
  • 创造者:Aho Winberger Kernighan
  • 基于模式匹配检查输入文本,逐行处理并输出,获取指定的数据
  • awk过滤数据时支持仅打印某一列,如:第2列、第4列…
  • awk命令格式1:awk [选项] ‘条件1{指令} 条件2{指令}’ 文件名
  • awk命令格式2:前置命令 | awk [选项] ‘条件{指令}’
  • 常用指令:print 是最常用的打印指令
  • 常用选项:-F #指定分隔符,如不指定分隔符,默认以空格或tab键为默认分隔符,可通过[]集合匹配多种单个字符
  • awk内置变量:$1第一列,$2第二列,$3第三列,依次类推,NR文件当前行号,NF文件当前列数
  • 命令格式1示例:
  1. #准备素材
  2. [root@localhost opt]# vim test.txt
  3. hello the woman
  4. welcome to china
  5. #打印文件的第一列
  6. [root@localhost opt]# awk '{print $1}' test.txt
  7. hello
  8. welcome
  9. #打印文件第一列和第三列
  10. [root@localhost opt]# awk '{print $1,$3}' test.txt
  11. hello woman
  12. welcome china
  13. #打印passwd文件第一列(默认没有空格与tab键作为分隔符,打印文件所有内容)
  14. [root@localhost opt]# awk '{print $1}' /etc/passwd
  15. #手动指定以:作为分隔,打印文件第一列
  16. [root@localhost opt]# awk -F: '{print $1}' /etc/passwd
  17. #打印文件第一列与第七列
  18. [root@localhost opt]# awk -F: '{print $1,$7}' /etc/passwd
  19. #通过[]集合匹配多种单个字符作为分隔符,打印用户名与解释器字段
  20. [root@localhost opt]# awk -F[:/] '{print $1,$10}' /etc/passwd
  21. #通过正则表达式过滤以root开头的行
  22. [root@localhost opt]# awk -F: '/^root/{print}' /etc/passwd
  23. root:x:0:0:root:/root:/bin/bash
  24. #通过正则表达式过滤以root开头的行,打印第1列与第7列
  25. [root@localhost opt]# awk -F: '/^root/ {print $1,$7}' /etc/passwd
  26. root /bin/bash
  27. #打印文件每一行与每一行的列数
  28. [root@localhost opt]# awk -F: '{print NR,NF}' /etc/passwd
  29. #打印文件每一行与每一行的列数,并打印最后一列
  30. [root@localhost opt]# awk -F: '{print NR,NF,$NF}' /etc/passwd
  31. #通过常量打印执行的列
  32. [root@localhost opt]# awk -F: '{print $1,"用户的解释器为:",$7}' /etc/passwd
  33. root 用户的解释器为: /bin/bash
  34. #匹配第一列包含root的行
  35. [root@localhost opt]# awk -F: '$1~/root/' /etc/passwd
  36. root:x:0:0:root:/root:/bin/bash
  37. #排除第7列noloogin的行,打印第1列与第7列
  38. [root@localhost opt]# awk -F: '$7!~/nologin/{print $1,$7}' /etc/passwd
  39. #利用扩展正则过滤,以root或者adm开头的行,打印第1列与第7列
  40. [root@localhost opt]# awk -F: '/^(root|adm)/{print $1,$7}' /etc/passwd
  41. root /bin/bash
  42. adm /sbin/nologin

awk使用数值/字符串比较设置条件

  • 等于: ==
  • 不等于: !=
  • 大于: >
  • 大于等于: >=
  • 小于: <
  • 小于等于:<=
  1. #打印行号等于3
  2. [root@localhost opt]# awk 'NR==3{print}' /etc/passwd
  3. daemon:x:2:2:daemon:/sbin:/sbin/nologin
  4. #使用sed更加方便打印某一行
  5. [root@localhost opt]# sed -n '3p' /etc/passwd
  6. daemon:x:2:2:daemon:/sbin:/sbin/nologin
  7. #打印文件中第3列大于等于1000,打印第1列,第3列,第7列
  8. [root@localhost opt]# awk -F: '$3>=1000{print $1,$3,$7}' /etc/passwd
  9. lisi 1000 /bin/bash
  10. #打印文件中第三列小于1000,打印第1列,第3列,第7列
  11. [root@localhost opt]# awk -F: '$3<1000{print $1,$3,$7}' /etc/passwd
  12. root 0 /bin/bash
  13. #打印文件中第3列大于500并且小于1000,打印第1列,第3列,第7列
  14. [root@localhost opt]# awk -F: '$3>500 && $3<1000 {print $1,$3,$7}' /etc/passwd
  15. polkitd 999 /sbin/nologin
  16. #打印第一列不等于root的行
  17. [root@localhost opt]# awk -F: '$1!="root"{print}' /etc/passwd

awk过滤时机:awk ‘BEGIN{指令} {指令} END{指令}’ 文件名

  • BEGIN{指令} #读取文件内容之前执行指令,指令执行一次,行前处理
  • {指令} #读取文件过程中执行,指令逐行执行,读一行,执行一次
  • END{指令} #读取文件内容结束后执行指令,指令执行一次,行后处理
  1. #BEGIN{指令}行前处理
  2. [root@localhost opt]# awk 'BEGIN{print "正在处理中"}'
  3. 正在处理中
  4. #定义变量
  5. [root@localhost opt]# awk "BEGIN{x=10;print x}"
  6. 10
  7. #四则运算
  8. [root@localhost opt]# awk "BEGIN{x=10;print x+5}"
  9. 15
  10. [root@localhost opt]# awk "BEGIN{x=10;print x+5}"
  11. 15
  12. [root@localhost opt]# awk "BEGIN{x=10;print x-5}"
  13. 5
  14. [root@localhost opt]# awk "BEGIN{x=10;print x*5}"
  15. 50
  16. [root@localhost opt]# awk "BEGIN{x=10;print x/5}"
  17. 2
  18. [root@localhost opt]# awk "BEGIN{print 10+10}"
  19. 20
  20. [root@localhost opt]# awk "BEGIN{print 10-5}"
  21. 5
  22. [root@localhost opt]# awk "BEGIN{print 10*2}"
  23. 20
  24. [root@localhost opt]# awk "BEGIN{print 10/3}"
  25. 3.33333
  26. [root@localhost opt]# awk "BEGIN{print 10%3}"
  27. 1
  28. #通过awk统计系统里使用bash解释器的用户有什么个?
  29. [root@localhost opt]# awk 'BEGIN{x=0}/bash$/{x++}END{print x}' /etc/passwd
  30. 27
  31. [root@localhost opt]# awk '/bash$/{x++}END{print x}' /etc/passwd
  32. 27

awk分支结构

  • if单分支格式:if(条件){指令}
  • if双分支格式:if(条件){指令}else{指令}
  1. #if单分支统计passwd文件中UID大于或等于1000的用户个数
  2. awk -F: '{if($3>=1000){x++}} END{print x}' /etc/passwd
  3. if($3>=1000){x++}
  4. [root@localhost ~]# awk -F: '{if($3>=1000){x++}}END{print x}' /etc/passwd
  5. #if双分支统计passwd文件中UID大于等于1000的用户,和小于1000的用户个数
  6. [root@localhost ~]# awk -F: '{if($3>=1000){i++} else{x++}} END{print i,x}' /etc/passwd

awk数组

  • 定义数组格式1:数组名[下标]=值
  • 定义数组格式2:数组名[下标]
  • 数组的用法:for(变量名 in 数组名) {print 数组名[变量]}
  1. #awk定义数组方式
  2. [root@localhost ~]# awk 'BEGIN{x[0]=10;x[1]=20;print x[0],x[1]}'
  3. 10 20
  4. #awk定义数组方式
  5. [root@localhost ~]# awk 'BEGIN{x[0]++;print x[0]}'
  6. 1

awk循环结构

  • 命令格式:for(变量名 in 数组名){print 数组名[变量]}
  1. [root@localhost ~]# awk 'BEGIN{a[0]=00;a[1]=11;a[2]=22;for(i in a){print i,a[i]}}'
  2. 0 0
  3. 1 11
  4. 2 22
  • awk命令格式2:前置命令 | awk [选项] ‘条件{指令}’
  1. #通过awk打印剩余内存
  2. [root@localhost opt]# free -h | grep Mem | awk '{print $4}'
  3. 134M
  4. [root@localhost opt]# free -h | awk '/Mem/{print $4}'
  5. 134M
  6. #用awk写一个监控脚本,监控网卡的进出口流量
  7. [root@localhost ~]# vim while_liuliang.sh
  8. #!/bin/bash
  9. while :
  10. do
  11. clear
  12. ifconfig ens32 | awk '/inet /{print "IP:",$2}'
  13. ifconfig ens32 | awk '/RX p/{print "入口流量:",$5}'
  14. ifconfig ens32 | awk '/TX p/{print "出口流量:",$5}'
  15. sleep 0.1
  16. done
  17. #使用awk过滤系统根分区使用情况
  18. [root@localhost ~]# df -h | grep '/$' | awk '{print $4}' | awk -FG '{print $1}'
  19. 51
  20. #过滤根分区剩余空间与物理内存空间
  21. [root@localhost ~]# vim df_free.sh
  22. #!/bin/bash
  23. df -h | grep '/$' | awk '{print "根分区剩余空间:",$4}'
  24. free -h | grep Mem | awk '{print "物理内存剩余空间:", $4}'
  25. #通过awk统计用户登录系统的次数
  26. [root@localhost ~]# who | awk '{ip[$1]++}END{for(i in ip)print i,ip[i]}'
  27. root 1

cron周期性计划任务

  • cron周期性计划任务用来定期执行程序,目前最主要的用途是定期备份数据
  • 软件包名:cronie、crontabs
  • 服务名:crond
  • 日志文件:/var/log/cron

cron定义时间格式

* 执行的命令
分 时 日 月 周
分钟:从0到59之间的整数
小时:从0到23之间的整数
日期:从1到31之间的整数
月份:从1到12之间的整数
星期:0~6之间的整数,0代表周日
* #每分,每时,每天,每月,每周
, #分隔多个不连续的时间
- #指定连续时间范围
/ #指定执行任务的时间间隔

  1. #软件包默认系统自动安装
  2. [root@localhost ~]# rpm -q cronie
  3. cronie-1.4.11-19.el7.x86_64
  4. #服务默认随机自启
  5. [root@localhost ~]# systemctl status crond
  6. #cron定义时间格式
  7. * * * * * 执行的命令
  8. 分钟:从059之间的整数
  9. 小时:从023之间的整数
  10. 日期:从131之间的整数
  11. 月份:从112之间的整数
  12. 星期:0~6之间的整数,0代表周日
  13. * #每分,每时,每天,每月,每周
  14. #分隔多个不连续的时间
  15. - #指定连续时间范围
  16. / #指定执行任务的时间间隔
  17. #每周5在上8点执行一个任务
  18. 00 8 * * 5 xx命令
  19. #每天晚上23:30执行一个任务
  20. 30 23 * * * xx命令
  21. #日期跟星期不能同时定义,发生矛盾(没有这么定义的!)
  22. 30 23 1 * 2 xx命令
  23. #每月1号23:30分执行一个任务
  24. 30 23 1 * * xx命令
  25. #每月1、3、5号23:30执行一个任务
  26. 30 23 1,3,5 * * xx命令
  27. #每周1、3、5凌晨3点执行一个任务
  28. 00 3 * * 1,3,5 xx命令
  29. #每月2-5号凌晨3:30分执行一个任务
  30. 30 3 2-5 * * xx命令
  31. #每两小时执行一个任务
  32. * */2 * * * xx命令
  33. #每两分钟执行一个任务
  34. */2 * * * * xx命令
  • crontab:用于管理计划任务
  • crontab -e -u 用户名 #编写计划任务
  • crontab -l -u 用户名 #查看计划任务
  • crontab -r -u 用户名 #清楚计划任务
  1. #每一分钟执行一个任务
  2. [root@localhost ~]# crontab -e
  3. */1 * * * * date >> /opt/date.txt
  4. [root@localhost ~]# cat /opt/date.txt
  5. 2021 05 23 星期日 17:30:02 CST
  6. #每周6凌晨3:30分备份/var/log/日志文件
  7. [root@localhost ~]# crontab -e
  8. 30 3 * * 6 tar -czf `date +%F`-log.tar.gz /var/log/*.log
  9. #查看计划任务
  10. [root@localhost ~]# crontab -l
  11. 30 3 * * 6 tar -czf `date +%F`-log.tar.gz /var/log/*.log
  12. #清除计划任务
  13. [root@localhost ~]# crontab -r
  14. [root@localhost ~]# crontab -l
  15. no crontab for root

SELinux系统内核安全机制

  • Security-Enhanced Linux 美国NSA国家安全局主导开发,一套增强Linux系统安全的强制访问控制体系
  • 集成到Linux内核(2.6及以上)针对用户、进程、目录和文件提供了预设的保护策略,以及管理工具
  • SELinux运行模式
    • enforcing #强制模式
    • permissive #宽松模式
    • disabled #禁用模式
  • SELinux运行模式切换
    • 查看当前运行模式:getenforce
    • 临时切换运行模式:setenforce 1|0 #1强制模式,0宽松模式
  1. #查看当前运行模式
  2. [root@localhost ~]# getenforce
  3. Enforcing #默认为强制模式
  4. #切换运行模式为宽松模式
  5. [root@localhost ~]# setenforce 0
  6. [root@localhost ~]# getenforce
  7. Permissive
  8. #切换运行模式为强制模式
  9. [root@localhost ~]# setenforce 1
  10. [root@localhost ~]# getenforce
  11. Enforcing
  • SELinux配置文件:/etc/selinux/config
  1. #永久修改运行模式
  2. [root@localhost ~]# vim /etc/selinux/config
  3. ...
  4. SELINUX=disabled

环境准备

  1. #安装httpd与vsftpd服务
  2. [root@localhost ~]# rpm -q httpd
  3. httpd-2.4.6-88.el7.centos.x86_64
  4. [root@localhost ~]# rpm -q vsftpd
  5. vsftpd-3.0.2-25.el7.x86_64
  6. #启动服务
  7. [root@localhost ~]# systemctl start httpd
  8. [root@localhost ~]# systemctl start vsftpd
  9. #查看运行状态
  10. [root@localhost ~]# systemctl status httpd
  11. [root@localhost ~]# systemctl status vsftpd
  12. #关闭防火墙
  13. [root@localhost ~]# systemctl stop firewalld

常见协议及端口

  • http:超文本传输协议(明文协议) 默认端口:80 httpd默认走的http协议
  • https:安全的超文本传输协议 默认端口:443 加密网站
  • ftp:文件传输协议 默认端口:20(数据端口)21(命令端口)
  • tftp:简单的文件传输协议 默认端口:69
  • DNS:域名解析协议 默认端口:53
  • ssh:远程连接协议 默认端口:22
  • telnet:远程管理协议 默认端口:23
  • smtp:用户发邮件协议 默认端口:25

  • /etc/services 文件记录协议及端口信息

安全防护firewalld防火墙

  • 防火墙分为硬件防火墙和软件防火墙
  • 系统服务:firewalld,CentOS7系统默认使用的防火墙,CentOS6系统默认使用的防火强iptables
  • 防火墙:匹配即停止
  • 管理工具:firewalld-cmd
  • 防火墙预设安全区域
    • public:仅允许访问本机的sshd、DHCP、ping等少量服务
    • trusted:允许任何访问
    • 单独允许某一个IP 是写入trust
    • block:拒绝任何来访请求
    • drop:丢弃任何来访的数据包
  1. #开启防火墙
  2. [root@localhost ~]# systemctl start firewalld
  3. #查看默认区域
  4. [root@localhost ~]# firewall-cmd --get-default-zone
  5. public
  6. #修改默认区域
  7. firewall-cmd --set-default-zone=区域名
  8. #将默认区域修改为block
  9. [root@localhost ~]# firewall-cmd --set-default-zone=block
  10. success
  11. [root@localhost ~]# firewall-cmd --get-default-zone
  12. block
  13. #将默认区域修改为dorp
  14. [root@localhost ~]# firewall-cmd --set-default-zone=drop
  15. success
  16. [root@localhost ~]# firewall-cmd --get-default-zone
  17. drop
  18. #将默认区域修改为public
  19. [root@localhost ~]# firewall-cmd --set-default-zone=public
  20. success
  21. [root@localhost ~]# firewall-cmd --get-default-zone
  22. public
  23. #查看区域规则
  24. firewall-cmd --zone=区域名 --list-all
  25. #查看public所有规则
  26. [root@localhost ~]# firewall-cmd --zone=public --list-all
  27. public (active)
  28. target: default #默认区域
  29. icmp-block-inversion: no
  30. interfaces: ens32
  31. sources:
  32. services: ssh dhcpv6-client #允许访问的服务
  33. ports:
  34. protocols:
  35. masquerade: no
  36. forward-ports:
  37. source-ports:
  38. icmp-blocks:
  39. rich rules:
  40. #为public区域添加http协议,使用 --add-service=服务名
  41. [root@localhost ~]# firewall-cmd --zone=public --add-service=http
  42. success
  43. [root@localhost ~]# firewall-cmd --zone=public --list-all
  44. public (active)
  45. target: default
  46. icmp-block-inversion: no
  47. interfaces: ens32
  48. sources:
  49. services: ssh dhcpv6-client http #添加http协议
  50. ports:
  51. protocols:
  52. masquerade: no
  53. forward-ports:
  54. source-ports:
  55. icmp-blocks:
  56. rich rules:
  57. #为public添加ftp协议
  58. [root@localhost ~]# firewall-cmd --zone=public --add-service=ftp
  59. success
  60. [root@localhost ~]# firewall-cmd --zone=public --list-all
  61. public (active)
  62. target: default
  63. icmp-block-inversion: no
  64. interfaces: ens32
  65. sources:
  66. services: ssh dhcpv6-client http ftp #添加ftp协议
  67. ports:
  68. protocols:
  69. masquerade: no
  70. forward-ports:
  71. source-ports:
  72. icmp-blocks:
  73. rich rules:

封网段开服务

  1. #若针对永久配置需添加 --permanent
  2. #使用 -- add-source=网段地址
  3. #为public区域永久添加http协议
  4. [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=http
  5. success
  6. [root@localhost ~]# firewall-cmd --zone=public --list-all
  7. public (active)
  8. target: default
  9. icmp-block-inversion: no
  10. interfaces: ens32
  11. sources:
  12. services: ssh dhcpv6-client http ftp
  13. ports:
  14. protocols:
  15. masquerade: no
  16. forward-ports:
  17. source-ports:
  18. icmp-blocks:
  19. rich rules:
  20. #为public区域永久添加ftp协议
  21. [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=ftp
  22. success
  23. [root@localhost ~]# firewall-cmd --zone=public --list-all
  24. public (active)
  25. target: default
  26. icmp-block-inversion: no
  27. interfaces: ens32
  28. sources:
  29. services: ssh dhcpv6-client http ftp
  30. ports:
  31. protocols:
  32. masquerade: no
  33. forward-ports:
  34. source-ports:
  35. icmp-blocks:
  36. rich rules:
  37. #永久修改需重新加载防火墙配置
  38. firewall-cmd --reload
  39. [root@localhost ~]# firewall-cmd --reload
  40. success
  41. #单独拒绝某一个IP
  42. [root@localhost ~]# firewall-cmd --zone=block --add-source=192.168.0.24
  43. success
  44. [root@localhost ~]# firewall-cmd --zone=block --list-all
  45. block (active)
  46. target: %%REJECT%%
  47. icmp-block-inversion: no
  48. interfaces:
  49. sources: 192.168.0.24
  50. services:
  51. ports:
  52. protocols:
  53. masquerade: no
  54. forward-ports:
  55. source-ports:
  56. icmp-blocks:
  57. rich rules:
  58. #删除规则:--remove-source
  59. #删除block区域的指定IP
  60. [root@localhost ~]# firewall-cmd --zone=block --remove-source=192.168.0.24
  61. success
  62. [root@localhost ~]# firewall-cmd --zone=block --list-all
  63. block
  64. #删除public区域的ftp协议
  65. [root@localhost ~]# firewall-cmd --zone=public --remove-service=ftp
  66. success
  67. [root@localhost ~]# firewall-cmd --zone=public --list-all
  68. public (active)
  69. target: default
  70. icmp-block-inversion: no
  71. interfaces: ens32
  72. sources:
  73. services: ssh dhcpv6-client http
  • 防火墙端口映射
  • 本地应用的端口重定向(端口1 > 端口2)从客户机访问 端口1 的请求,自动映射到本机端口2
  1. #当有人访问5432端口时,映射到本机的80端口
  2. [root@localhost ~]# firewall-cmd --zone=public --add-forward-port=port=5432:proto=tcp:toport=80
  3. success
  4. #命令解释:
  5. --add--forward #添加转发端口
  6. port=port=5432 #指定转发的端口
  7. proto=tcp #指定tcp协议
  8. toport=80 #指定目标端口
  9. [root@localhost ~]# firewall-cmd --zone=public --list-all
  10. public (active)
  11. target: default
  12. icmp-block-inversion: no
  13. interfaces: ens32
  14. sources:
  15. services: ssh dhcpv6-client http
  16. ports:
  17. protocols:
  18. masquerade: no
  19. forward-ports: port=5432:proto=tcp:toport=80:toaddr=
  20. source-ports:
  21. icmp-blocks:
  22. rich rules:

iptables防火墙 ————匹配及停止

  • nerfilter/iptables:工作在主机或网络的边缘,对于进出本主机或网络的报文根据事先定义好的检查规则作匹配检测,对于能够被规则所匹配到的报文做出相应的处理

iptables框架

iptables的4表

  • filter:数据过滤表
    • 包含三个链:INPUT,UOTPUT,FORWARD
  • nat:地址转换表,不能过滤数据包,仅仅修改数据包中的IP和端口
    • 包含三个链:PREROUTING,POSTROUTING,OUTPUT
  • raw:状态跟踪表,决定是否跟踪数据包
    • 包含两个链:OUTPUT,PREROUTING
  • mangle:包标记表,不能过滤也不能修改数据包

    • 包含五个链:PREROUTING,FORWARD,POSTROUTING,INPUT,OUTPUT

      iptables的5链

  • PREROUTING链:路由前规则,防火墙在刚刚接收到数据包,对数据包进行路径选择之前所需要的链

  • FORWARD链:转发规则,将数据包从一个网络转发到另外一个网络所需要的链
  • POSTROUTING链:路由后规则,对数据包进行路径选择后,并在防火墙即将把数据包转发出去之前,所要需要的链
  • INPUT链:入站规则,限制客户端数据包目地地址是防火墙主机的上层应用所需要的链
  • OUTPUT链:出站规则,限制防火墙主机上层应用产生的数据包是否可以出站需要的链

    目标操作

  • ACCEPT:允许通过/放行

  • DROP:直接丢弃,不给出任何回应
  • REJECT:拒绝通过
  • LOG:记录日志,然后传给下一条规则

iptables命令格式

  • 命令格式:Iptables [-t 表名] 选项 [链名] [条件] [-j 目标操作]
  • 添加规则:
    • -A #追加一条防火墙规则至链的末尾
    • -I #插入一条防火墙规则至链的开头
  • 查看规则:
    • -L #查看iptables所有规则
    • -n #以数字形式显示地址、端口等信息
    • —line-numbers #查看规则时,显示规则的行号
  • 删除规则:
    • -D #删除链内指定的序号(或内容)的一条规则
    • -F #清空所有规则
  • 默认规则:
    • -P #为指定的链设置默认规则

iptables防火墙规则的条件

  • 通用匹配:
    • 协议匹配:-p #协议名称
    • 地址匹配:-s 源地址、-d 目标地址
    • 接口匹配:-i 接受数据的网卡、-o 发送数据的网卡
    • 端口匹配:—sport 源端口号、—dport 目标端口号
    • ICMP类别匹配:—icmp-type ICMP 类型
  • 创建规则注意事项
  1. 可以不指定表,默认为filter表
  2. 如果没有找到匹配条件,执行防火墙默认规则
  3. 选项/链名/目标操作用大写字母,其余都小写

主机型防火墙规则配置

  1. #安装iptables服务
  2. [root@master ~]# yum -y install iptables-services
  3. [root@master ~]# systemctl start iptables
  4. #拒绝icmp访问
  5. [root@master ~]# iptables -t filter -I INPUT -p icmp -j REJECT
  6. #查看规则
  7. [root@master ~]# iptables -L -n --line-numbers
  8. #测试icmp访问
  9. [root@slave ~]# ping 192.168.0.10
  10. PING 192.168.0.10 (192.168.0.10) 56(84) bytes of data.
  11. From 192.168.0.10 icmp_seq=1 Destination Port Unreachable
  12. [root@master ~]# iptables -t filter -I INPUT -p icmp -j DROP
  13. [root@master ~]# iptables -t filter -I INPUT -p icmp -j ACCEPT
  14. #清空某一条规则(默认为filter表)
  15. [root@iptables ~]# iptables -t filter -D INPUT 8
  16. #清空所有规则(默认为filter表所有规则)
  17. [root@master ~]# iptables -F
  18. #清空其他表所有规则
  19. [root@master ~]# iptables -t nat -F
  20. [root@master ~]# iptables -t raw -F
  21. [root@master ~]# iptables -t mangle -F
  22. #为filter表INPUT链添加规则,允许任何人使用TCP协议访问本机
  23. [root@master ~]# iptables -t filter -I INPUT -p tcp -j ACCEPT
  24. #为filter表INPUT链添加规则至第一行,允许任何人使用UDP协议访问本机
  25. [root@master ~]# iptables -t filter -I INPUT -p udp -j ACCEPT
  26. #为filter表INPUT链添加规则至第二行,允许任何人使用ICMP协议访问本机
  27. [root@master ~]# iptables -t filter -I INPUT 2 -p icmp -j ACCEPT
  28. [root@master ~]# iptables -nL
  29. Chain INPUT (policy ACCEPT)
  30. target prot opt source destination
  31. ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0
  32. ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
  33. ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0
  34. #查看INPUT链规则
  35. [root@master ~]# iptables -nL INPUT
  36. Chain INPUT (policy ACCEPT)
  37. target prot opt source destination
  38. ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0
  39. ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
  40. ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0
  41. #清空filter表所有规则
  42. [root@master ~]# iptables -F

设置防火墙默认规则

  1. #查看filter表
  2. [root@master ~]# iptables -t filter -nL
  3. Chain INPUT (policy ACCEPT) //默认规则
  4. target prot opt source destination
  5. Chain FORWARD (policy ACCEPT) //默认规则
  6. target prot opt source destination
  7. Chain OUTPUT (policy ACCEPT) //默认规则
  8. target prot opt source destination
  9. #允许22号端口被访问
  10. [root@master ~]# iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT
  11. [root@master ~]# iptables -nL
  12. Chain INPUT (policy ACCEPT)
  13. target prot opt source destination
  14. ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
  15. #将filter表INPUT链默认规则修改为DROP
  16. [root@master ~]# iptables -t filter -P INPUT DROP
  17. [root@master ~]# iptables -nL
  18. Chain INPUT (policy DROP) #默认为拒绝
  19. target prot opt source destination
  20. ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 #只允许22端口访问,其他全部拒绝
  1. #将默认规则修改为ACCEPT
  2. [root@master ~]# iptables -t filter -P INPUT ACCEPT
  3. #清空防火墙规则
  4. [root@master ~]# iptables -F
  5. #设置防火墙拒绝所有80端口的访问
  6. [root@master ~]# iptables -t filter -I INPUT -p tcp --dport 80 -j REJECT
  7. #查看规则
  8. [root@master ~]# iptables -nL
  9. #安装httpd服务
  10. [root@master ~]# yum -y install httpd
  11. #启动服务
  12. [root@master ~]# systemctl start httpd
  13. #修改默认首页
  14. [root@master ~]# echo xxoo > /var/www/index.html
  15. #访问测试
  16. [root@slave ~]# curl http://192.168.0.10
  17. [root@master ~]# iptables -F
  18. #单独拒绝某个IP
  19. [root@master ~]# iptables -t filter -I INPUT -s 192.168.0.20 -j REJECT
  20. #查看规则
  21. [root@master ~]# iptables -nL
  22. Chain INPUT (policy ACCEPT)
  23. target prot opt source destination
  24. REJECT all -- 192.168.0.20 0.0.0.0/0 reject-with icmp-port-unreachable
  25. 192.168.0.20访问测试
  26. [root@slave ~]# curl http://192.168.0.10
  27. curl: (7) Failed connect to 192.168.0.10:80; 拒绝连接
  28. #拒绝客户端访问本机网卡的80端口
  29. [root@master ~]# iptables -t filter -I INPUT -i ens32 -p tcp --dport 80 -j REJECT
  30. #客户端测试
  31. [root@agent ~]# curl http://192.168.0.10
  32. curl: (7) Failed connect to 192.168.0.10:80; 拒绝连接
  33. [root@master ~]# iptables -F
  34. #设置防火墙拒绝某个网段
  35. [root@master ~]# iptables -t filter -I INPUT -s 192.168.1.0/24 -j REJECT
  36. #查看规则
  37. [root@master ~]# iptables -nL
  38. Chain INPUT (policy ACCEPT)
  39. target prot opt source destination
  40. REJECT all -- 192.168.1.0/24 0.0.0.0/0

网络型防火墙规则配置

  • 通过路由转发配置网络型防火墙 | 主机名 | 网卡、IP地址、网关设置 | | —- | —- | | client28 | ens32:192.168.1.24,网关指向防火墙外网IP:192.168.1.100 | | proxy | ens32内网IP:192.168.0.26,ens34外网IP:192.168.1.100 | | web27 | ens32:192.168.0.27,网关指向防火墙内网IP:192.168.0.26 |
  • 防火墙主机添加网卡并设置IP,IP设置为:192.168.0.100/24
  1. #开启路由转发功能
  2. [root@proxy ~]# echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
  3. [root@proxy ~]# sysctl -p //加载配置立即生效
  4. net.ipv4.ip_forward = 1
  5. #查看路由转发
  6. [root@proxy ~]# cat /proc/sys/net/ipv4/ip_forward
  7. 1
  • 第二台服务器提供网站服务:web27将网关指向1192.168.0.26
  1. #安装httpd服务
  2. [root@web1 ~]# yum -y install httpd
  3. #修改默认首页
  4. [root@web1 ~]# echo web27 > /var/www/html/index.html
  5. [root@web1 ~]# systemctl start httpd
  6. [root@web1 ~]# systemctl status httpd
  • 第三台为客户端:client将IP修改为192.168.1.30网段,将网关指向防火墙主机的第二块网卡:192.168.0.100
  • 访问测试:curl http://192.168.0.20

  • 防火墙主机配置规则:拒绝192.168.1.30访问80端口
  1. [root@proxy ~]# iptables -I FORWARD -s 192.168.1.30 -p tcp --dport 80 -j DROP
  2. #客户端192.168.1.30访问测试:
  3. curl http://192.168.0.20
  4. #拒绝所有客户端地址访问内网80端口
  5. [root@iptables ~]# iptables -t filter -I FORWARD -p tcp --dport 80 -j REJECT
  6. [root@proxy ~]# iptables -F

防火墙扩展

  • 命令格式:iptables 选项 链名 -m 扩展模块 —具体扩展条件 -j 动作
  1. #根据MAC地址封锁主机,安装nmap扫描获取地方IP的MAC地址
  2. [root@proxy ~]# yum -y install nmap
  3. #扫描对方主机IP
  4. [root@proxy ~]# nmap -s 192.168.1.28
  5. Starting Nmap 6.40 ( http://nmap.org ) at 2020-09-25 17:12 CST
  6. Nmap scan report for 192.168.0.111
  7. Host is up (0.00044s latency). //当前主机状态
  8. MAC Address: 00:0C:29:CA:87:81 (VMware) //MAC地址
  9. Nmap done: 1 IP address (1 host up) scanned in 4.05 seconds
  10. #通过MAC地址限制对方访问
  11. [root@proxy ~]# iptables -t filter -I FORWARD -p tcp --dport 80 -m mac --mac-source 00:0C:29:D5:29:0F -j REJECT

基于多端口设置过滤规则

  1. [root@proxy ~]# iptables -t filter -I FORWARD -p tcp -m multiport --dports 20,21,80,443 -j ACCEPT
  2. #multiport :多端口模块
  3. #根据IP范围设置封锁规则
  4. [root@proxy ~]# iptables -t filter -I FORWARD -p tcp --dport 80 -m iprange --src-range 192.168.1.20-192.168.1.30 -j REJECT
  5. #iprange模块:ip范围模块
  6. #--src-range:源IP
  7. #--dst-range:目标IP

配置SNAT实现共享上网

  • 通过防火墙规则,允许局域网中的主机访问外网 | 主机名 | 网卡、IP地址、网关 | | —- | —- | | 内部主机:host28 | ens32:192.168.1.28,网关:192.168.1.100 | | 内部防火墙:proxy | ens32外网IP:192.168.0.26,ens34内网IP:192.168.1.100 | | 外部主机:web27 | ens32:192.168.0.27,网关:192.168.0.26 |
  1. #实现192.168.1.28转换为192.168.0.26
  2. [root@proxy ~]# iptables -t nat -I POSTROUTING -s 192.168.1.0/24 -p tcp --dport 80 -j SNAT --to-source 192.168.0.26
  3. #POSTROUTING:路由后链
  4. #-s:指定源地址为192.168.1.0网段的地址
  5. #-p:想要通过tcp协议
  6. #--dport:访问目标的80端口时
  7. #-j:SNAT转换
  8. #--to-source:转换源地址为192.168.0.26
  9. #web1动态查看访问日志
  10. [root@web1 ~]# tail -f /var/log/httpd/access_log
  11. client 192.168.1.30访问网站
  12. curl http://192.168.0.27
  13. #所有iptables规则都是临时规则,如果需要永久保留规则需要执行如下命令
  14. [root@proxy ~]# service iptables save

sudo用户提权

  • 管理员提前为用户设置执行权限许可
  • 被授权用户有权执行授权命令
  • 配置文件:/etc/sudoers
  • 命令格式:sudo 特权命令
  1. #修改/etc/sudoers文件,为lisi用户授予相关脚本的执行权限,允许通过systemctl工具来管理系统服务,修改/etc/sudoers配置文件可以用vim编辑文件,或者使用visudo命令修改
  2. [root@master ~]# visudo
  3. .. ..
  4. root ALL=(ALL) ALL
  5. lisi ALL=(root) /bin/systemctl
  6. 解释:授权lisi用户以root身份执行systemctl命令
  7. #切换lisi用户验证sudo权限
  8. [root@master ~]# su - lisi
  9. [lisi@master ~]$ sudo -l
  10. .. ..
  11. 用户 lisi 可以在 master 上运行以下命令:
  12. (root) /bin/systemctl
  13. #通过sudo启动服务
  14. [lisi@master ~]$ sudo systemctl start httpd
  15. [lisi@master ~]$ sudo systemctl status httpd
  16. [lisi@master ~]$ sudo systemctl stop httpd
  17. #为lisi用户添加sudo权限,允许lisi用户可以创键用户,修改用户密码
  18. [root@master ~]# visudo
  19. .. ..
  20. lisi ALL=(root) /bin/systemctl,/sbin/useradd,/bin/passwd,!/bin/passwd root // ! 取反
  21. #切换lisi用户验证sudo权限
  22. [lisi@master ~]$ sudo useradd haha
  23. [lisi@master ~]$ id haha
  24. uid=1001(haha) gid=1001(haha) 组=1001(haha)
  25. #修改haha用户密码
  26. [lisi@master ~]$ sudo passwd haha
  27. 更改用户 haha 的密码
  28. 新的 密码:123
  29. 无效的密码: 密码少于 8 个字符
  30. 重新输入新的 密码:123
  31. passwd:所有的身份验证令牌已经成功更新。
  32. #为sudo机制启用日志记录,以便跟踪sudo执行操作
  33. [root@master ~]# visudo
  34. .. ..
  35. Defaults logfile="/var/log/sudo.log" #手动添加
  36. .. ..
  37. #普通用户执行sudo命令
  38. [lisi@master ~]$ sudo systemctl start httpd
  39. #查看日志是否记录
  40. [root@master ~]# cat /var/log/sudo.log
  41. Sep 24 12:57:09 : lisi : TTY=pts/1 ; PWD=/home/lisi ; USER=root ;
  42. COMMAND=/bin/systemctl start httpd

OpenSSH

  • OpenSSH开源免费提供ssh远程安全登录的程序
  • ssh协议端口:22/tcp
  • 服务名:sshd
  • ssh提供密钥认证登录方式
  1. #生成公私钥
  2. [root@localhost ~]# ssh-keygen
  3. Generating public/private rsa key pair.
  4. Enter file in which to save the key (/root/.ssh/id_rsa):
  5. Created directory '/root/.ssh'.
  6. Enter passphrase (empty for no passphrase):
  7. Enter same passphrase again:
  8. Your identification has been saved in /root/.ssh/id_rsa.
  9. Your public key has been saved in /root/.ssh/id_rsa.pub.
  10. The key fingerprint is:
  11. SHA256:Yjcq3+SAOmVQgCbRVC+6QgJp+rss5MK+anEwitmi4Xo root@localhost
  12. The key's randomart image is:
  13. +---[RSA 2048]----+
  14. |.=oo. |
  15. |oo. .. |
  16. |=. .. . |
  17. |+o.. . |
  18. |=++. o S |
  19. |O+.ooo + . |
  20. |Bo=oo o . |
  21. |+BEo o = |
  22. |O=*o . o |
  23. +----[SHA256]-----+
  24. #查看密钥文件
  25. [root@localhost ~]# ls .ssh
  26. id_rsa id_rsa.pub
  27. #将公钥拷贝至其他主机
  28. [root@localhost ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.0.27
  29. #其他主机查看公钥文件
  30. [root@host-27 ~]# ls .ssh
  31. authorized_keys
  32. #验证是否实现密钥认证登录
  33. [root@localhost ~]# ssh 192.168.0.27
  34. Last login: Sat Jun 5 00:41:47 2021 from 192.168.0.1
  35. [root@host-27 ~]#
  36. [root@host-27 ~]# exit
  37. 登出


scp远程复制工具

  • scp可以实现主机之间的文件拷贝
    1. #将本地文件拷贝至远程主机
    2. [root@localhost ~]# touch /opt/test.txt
    3. [root@localhost ~]# scp /opt/test.txt root@192.168.0.27:/opt
    4. #将远程主机文件拉取到本地
    5. [root@localhost ~]# scp root@192.168.0.27:/etc/fstab /opt
    6. [root@localhost ~]# ls /opt
    7. fstab test.txt

提高ssh服务安全性

  • 配置文件:/etc/ssh/sshd_config
    1. [root@master ~]# vim /etc/ssh/sshd_config
    2. .. ..
    3. #Port 22 #ssh默认监听端口
    4. #PermitRootLogin yes #是否允许root用户连接,yes允许,no不允许
    5. #PermitEmptyPasswords no #不允许空密码登录
    6. PasswordAuthentication yes #允许用密码登录
    7. AllowUsers 用户1 用户2 用户3@192.168.0.0/24 #定义账号白名单
    8. ##DenyUsers 用户1 用户2 #定义账号黑名单
    https://blog.csdn.net/qq_28513801/article/details/90696863

image.png

image.png

文件共享服务FTP介绍

  • FTP(File Transfet Protocol):文件传输协议
  • FTP是一种在互联网中基于TCP协议端到端的数据传输协议
  • 基于C/S架构,默认使用20、21号端口
  • 端口20(数据端口)用于数据传输
  • 端口21(命令端口)用于接收客户端发出的相关FTP命令

FTP工作模式

  • 主动模式:FTP客户端从本机的非特殊端口(>1023)连接FTP服务器的命令端口21,服务端通过本地的20号端口主动向客户端的随机端口发起连接请求,开始传输数据
  • 被动模式:FTP客户端通过向FTP服务器发送PASV命令进入被动模式,FTP服务器会另开一个随机端口,客户端主动连接到随机端口后,开始传输数据
  • 可以实现ftp功能的软件:
    • WU-ftpd:
    • proftpd:
    • pureftp:
    • vsftpd:非常安全的ftp服务器
    • ServU:
  • 客户端访问ftp服务器工具:
    • ftp
    • lftp、lftpget
    • wget
    • curl
    • FileZilla:windows客户端工具,可从软件商店直接下载

vsftpd介绍

  • vsftpd(very secure ftp daemon)非常安全的FTP守护进程
  • 是一款运行在Linux操作系统上开源且免费FTP服务程序
  • 不仅完全开源而且免费,还为我们提供了一个快速的、稳定并且安全的FTP服务

vsftpd用户模式

  • 本地用户
  • 虚拟用户
  • 匿名用户

vsftpd服务相关参数

  • /var/ftp #匿名用户共享目录
  • /etc/vsftpd #配置文件所在目录
  • /etc/vsftpd/vsftpd.conf #主配置文件
  • /usr/sbin/vsftpd #主程序文件
  • /etc/vsftpd/ftpusers #黑名单
  • /etc/vsftpd/user_list #控制名单(配置文件控制白名单与黑名单)
  • /var/log/xferlog #日志目录

vsftpd匿名用户模式

  1. #安装软件
  2. [root@ftp-server ~]# yum -y install vsftpd
  3. #启动服务
  4. [root@ftp-server ~]# systemctl start vsftpd
  5. #查看服务运行状态
  6. [root@ftp-server ~]# systemctl status vsftpd
  7. #客户端下载连接工具
  8. [root@client ~]# yum -y install ftp lftp
  9. #匿名用户权限介绍
  10. [root@localhost ftp]# vim /etc/vsftpd/vsftpd.conf
  11. ...
  12. 12 anonymous_enable=YES #是否允许匿名用户访问,yes允许,no不允许
  13. 29 #anon_upload_enable=YES #是否允许匿名用户上传,yes允许,no不允许
  14. 33 #anon_mkdir_write_enable=YES #是否允许匿名用户创建目录,yes允许,no不允许
  15. ...
  16. anon_other_write_enable=yes #是否允许匿名用户写权限,yes允许,no不允许(手动添加)

vsftpd本地用户模式

  1. #创建本地用户
  2. [root@localhost ~]# useradd ftpuser
  3. [root@localhost ~]# passwd ftpuser
  4. #修改主配置文件
  5. [root@localhost ~]# vim /etc/vsftpd/vsftpd.conf
  6. ...
  7. 12 anonymous_enable=NO #关闭匿名用户访问
  8. 16 local_enable=YES #是否允许本地用户访问,yes允许,no不允许
  9. 19 write_enable=YES #是否允许本地用户有写权限,yes允许,no不允许
  10. 23 local_umask=022 #本地用户上传文件默认权限为755
  11. 37 dirmessage_enable=YES #当用户第一次进入新目录时显示消息(了解)
  12. 40 xferlog_enable=YES #启动xferlog日志记录,该文件记录传输数据
  13. 53 #xferlog_file=/var/log/xferlog #日志文件位置,需删除注释
  14. 43 connect_from_port_20=YES #启用数据传输端口
  15. 49 #chown_username=whoever #改变上传文件的属主与属组
  16. 60 #idle_session_timeout=600 #客户端连接超时时间
  17. 63 #data_connection_timeout=120 #数据连接超时时间
  18. 101 chroot_local_user=YES #是否允许本地用户切换目录,yes不允许,no允许
  19. 115 listen=NO #是否开启监听IPV4的连接,默认没开启,改为yes
  20. 126 pam_service_name=vsftpd #启用pam认证的文件名称,路径为/etc/pam.d/vsftpd
  21. 127 userlist_enable=YES #是否启用控制名单文件,yes启用,no不启用,文件为/etc/vsftpd/user_list,如果启用控制名单功能,需要指定该文件为黑名单|白名单
  22. 128 userlist_deny=no #yes拒绝user_list文件中用户登录ftp服务器(黑名单),no允许登录(白名单)
  23. max_clients= #限制最大并发连接数量

NFS网络文件系统

  • NFS(Network File System)网络文件系统 , 是一种基于TCP/UDP传输协议的文件共享服务
  • NFS基于C/S架构,服务端启用协议将文件共享到网络上,然后允许本地NFS客户端通过网络挂载服务端共享的文件。
  • NFS基于RPC 远程过程调用机制, 支持在异构系统之间数据的传送 , RPC提供了一组与机器、操作系统以及低层传送协议无关的存取远程文件的操作
  • NFS协议:端口号 2049
  • 软件包:nfs-utils
  • 服务名:nfs
  • 配置文件:/etc/exports
  • RPC协议:端口号 111
  • 软件包:rpcbind
  • 服务名:rpcbind
  • NFS服务端配置
  1. #安装nfs服务端软件包
  2. [root@localhost ~]# yum -y install nfs-utils
  3. #启动nfs服务
  4. [root@localhost ~]# systemctl start nfs
  5. [root@localhost ~]# systemctl enable nfs
  6. #查看服务端口信息
  7. [root@localhost ~]# ss -anptul | grep 2049
  8. udp UNCONN 0 0 *:2049 *:*
  9. udp UNCONN 0 0 :::2049 :::*
  10. tcp LISTEN 0 64 *:2049 *:*
  11. tcp LISTEN 0 64 :::2049 :::*
  12. #查看RPC服务端口信息
  13. [root@localhost ~]# ss -anptul | grep rpcbind
  14. udp UNCONN 0 0 *:111
  15. tcp LISTEN 0 128 *:111
  16. #创建共享目录
  17. [root@localhost ~]# mkdir /upload
  18. #修改nfs主配置文件:/etc/exports
  19. [root@localhost ~]# vim /etc/exports
  20. /upload 192.168.0.27(rw) 192.168.0.28(ro)
  21. /test 192.168.0.0/24(rw) #共享给指定网段
  22. 共享文件夹路径 客户机地址(权限) 客户机地址(权限)
  23. #重启nfs服务
  24. [root@localhost ~]# systemctl restart nfs

客户端访问NFS

  1. #列出有哪些NFS共享资源:showmount -e 服务器地址,如果客户端没有该命令需安装nfs-utils
  2. [root@client ~]# showmount -e 192.168.0.26
  3. Export list for 192.168.0.26:
  4. /upload 192.168.0.28,192.168.0.27
  5. #手动挂载NFS共享:mount
  6. [root@client ~]# mkdir /opt/upload
  7. [root@client ~]# mount 192.168.0.26:/upload /opt/upload
  8. 服务器地址:文件夹路径 挂载点
  9. [root@client ~]# df -h
  10. 文件系统 容量 已用 可用 已用% 挂载点
  11. ...
  12. 192.168.0.26:/upload 17G 1.2G 16G 7% /opt/upload
  13. #客户端验证是否可以是否共享目录
  14. [root@client ~]# cd /opt/upload/
  15. [root@client upload]# touch xx.txt
  16. touch: 无法创建"xx.txt": 权限不够
  17. #解释:默认客户端是以nfs用户身份访问远端的nfs服务器,如果nfs服务端共享的目录属主为root用户,那客户端默认是没有写权限
  18. #服务端开放允许以root身份访问
  19. [root@localhost ~]# vim /etc/exports
  20. /upload 192.168.0.27(no_root_squash,rw) 192.168.0.28(ro)
  21. 解释:no_root_squash 不挤压root用户身份(允许以root身份访问)
  22. [root@localhost ~]# systemctl restart nfs
  23. #客户端验证
  24. [root@client upload]# touch xx.txt
  25. [root@client upload]# ls
  26. xx.txt
  27. #为普通用户授权访问nfs共享目录(通过ACL实现,nfs通过用户UID辨别用户身份)
  28. [root@localhost ~]# setfacl -m u:lisi:rwx /upload
  29. #设置SBIT权限
  30. [root@localhost ~]# chmod o+t /upload/
  31. #客户端lisi用户验证授权
  32. [lisi@client upload]$ touch lisi.txt
  33. [lisi@client upload]$ ls
  34. lisi.txt xx.txt
  35. [lisi@client upload]$ rm -rf xx.txt
  36. rm: 无法删除"xx.txt": 不允许的操作
  37. #客户端实现开机挂载配置:/etc/fstab
  38. [root@localhost]# vim /etc/fstab
  39. 192.168.0.220:/xxx /mnt/xxx nfs defaults,_netdev 0 0
  40. 服务器地址:文件夹路径 挂载点 文件系统 defaults,_netdev 0 0
  41. #解释:_netdev:指定nfs是网络设备

Apache httpd的web服务

适用于Unix/Linux下的web服务器软件

Apache httpd(开源且免费),虚拟主机,支持HTTPS协议,支持用户认证,支持单个目录的访问控制,支持URL地址重写,支持路径别名,支持反向代理和负载均衡,高度模块化设计,支持并发访问量20000左右

Tomcat(开源且免费):适合做java的网站

WebSphere:商业软件,适合做Java的网站

WebLogic:商业软件,适合做Java的网站

Jboss:红帽公司,商业软件,适合做Java的网站

Tengine:开源免费的web服务器软件,基于Nginx二次开发,淘宝正在使用一款web服务器软件

Nginx:开源免费的web服务器软件

httpd介绍

httpd是Apache基金会下一个开源且免费的web服务器软件,高度模块化设计

基于B/S(Browser/Server)模式:服务端提供页面,浏览器显示并下载页面

基于TCP/HTTP协议进行传输

安装httpd服务

软件包:httpd

系统服务:httpd

  1. #a安装httpd服务
  2. [root@localhost ~]# yum -y install httpd
  3. #启动httpd服务
  4. [root@localhost ~]# systemctl start httpd
  5. #查看服务运行状态
  6. [root@localhost ~]# systemctl status httpd
  7. #客户端访问
  8. curl http://192.168.0.26

服务相关参数

主配置文件:/etc/httpd/conf/httpd.conf

默认网页根目录:/var/www/html

默认网页文件名:index.html

提供的默认配置

  • Listen:监听地址:端口(80)
  • ServerName:注册的DNS域名
  • DocumentRoot:网页根目录(/var/www/html)
  • DirectoryIndex:默认首页文件名(index.heml)
  1. #修改主配置文件指定域名
  2. [root@localhost ~]# vim /etc/httpd/conf/httpd.conf
  3. ...
  4. ServerName www.abcd.com:80 #指定域名
  5. #重启httpd服务
  6. [root@localhost ~]# systemctl restart httpd
  7. #实现本地主机名与IP地址解析
  8. [root@localhost ~]# vim /etc/hosts
  9. ...
  10. 192.168.0.26 www.abcd.com
  11. #修改配置文件指定网页根目录存放位置
  12. [root@localhost ~]# vim /etc/httpd/conf/httpd.conf
  13. ...
  14. DocumentRoot "/var/www/myweb"
  15. #创建网页根目录
  16. [root@localhost ~]# mkdir /var/www/myweb
  17. #创建测试页面
  18. [root@localhost ~]# vim /var/www/myweb/index.html
  19. abcd
  20. #重启httpd服务
  21. [root@localhost ~]# systemctl restart httpd
  22. #访问测试:
  23. curl http://www.abcd.com
  24. abcd

httpd虚拟web主机

虚拟web主机的特点:由同一台主机提供多个web站点

虚拟web主机实现的三种方式:

  • 基于域名的虚拟主机:www.xxoo.com www.xxxx.com www.oooo.com
  • 基于端口的虚拟主机
  • 基于IP地址的虚拟主机

虚拟主机配置路径:/etc/httpd/conf.d/*.conf

虚拟主机配置:

ServerName 此站点的DNS名称

DocumentRoot 此站点的网页根目录
… …

基于域名虚拟web主机

image.png

  1. [root@localhost ~]# vim /etc/httpd/conf.d/web.conf
  2. <VirtualHost *:80>
  3. ServerName www.baidu.com
  4. DocumentRoot /var/www/baidu
  5. </VirtualHost>
  6. <VirtualHost *:80>
  7. ServerName www.nmsl.com
  8. DocumentRoot /var/www/nmsl
  9. </VirtualHost>
  10. <VirtualHost *:80>
  11. ServerName www.alg.com
  12. DocumentRoot /var/www/alg
  13. </VirtualHost>
  14. # 创建网页根目录
  15. [root@localhost ~]# mkdir /var/www/xxoo
  16. [root@localhost ~]# mkdir /var/www/xxxx
  17. [root@localhost ~]# mkdir /var/www/oooo
  18. #创建默认首页
  19. [root@localhost ~]# vim /var/www/xxoo/index.html
  20. xxoo
  21. [root@localhost ~]# vim /var/www/xxxx/index.html
  22. xxxx
  23. [root@localhost ~]# vim /var/www/oooo/index.html
  24. oooo
  25. #配置本地解析——客户端配置(谁访问谁配)
  26. [root@localhost ~]# vim /etc/hosts
  27. 192.168.0.26 www.xxoo.com
  28. 192.168.0.26 www.xxxx.com
  29. 192.168.0.26 www.oooo.com
  30. #重启服务
  31. [root@localhost ~]# systemctl restart httpd
  32. #访问测试
  33. [root@localhost ~]# curl http://www.xxoo.com
  34. xxoo
  35. [root@localhost ~]# curl http://www.xxxx.com
  36. xxxx
  37. [root@localhost ~]# curl http://www.oooo.com
  38. oooo

Ansible自动化运维

Ansible是2013年推出的一款IT自动化DevOps软件,基于Python语言开发,2015年被RedHat收购

Ansible特点:

Ansible基于Paramiko实现SSH协议链接通讯,默认只要被管理节点开启SSH服务,Ansible就可以管理远程主机

使用Ansible不需要在客户端主机(被管理主机)安装Agent

Ansible模块化设计,并且模块丰富,支持自定义模块,自定义模块可用任何语言编写

Ansible基于PyYAML模块支持Playbook,可以通过Playbook完成可重复的复杂工作

支持Jinjia2模板

官网:https://www.ansible.com/

批量管理工具:

  • Ansible:基于Python语言开发,轻量级批量管理工具
  • SaltStack:基于Python语言开发 ,C/S架构
  • Puppet:基于Ruby语言开发
  • Chef:基于Ruby语言开发

实验环境准备

  • 实验机3台,1台为ansible管理主机,2为被管理主机
  • 管理主机名称与IP地址:
    ansible-server,IP地址:192.168.0.26
  • 被管理主机名称与IP地址:
    web1,IP地址:192.168.0.27
    web2,IP地址:192.168.0.28

    关闭防火墙与SElinux

  1. [root@ansible-server ~]# systemctl stop firewalld
  2. [root@ansible-server ~]# systemctl disable firewalld
  3. [root@ansible-server ~]# setenforce 0
  4. [root@ansible-server ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

管理节点修改/etc/hosts文件实现本地解析

  1. [root@ansible-server ~]# vim /etc/hosts
  2. ...
  3. 192.168.0.26 web1
  4. 192.168.0.27 web2
  5. 192.168.0.28 web3

管理节点与被管理节点实现SSH密钥认证

  1. [root@ansible-server ~]# ssh-keygen

传递公钥到被管理节点

  1. [root@ansible-server ~]# for i in web1 web2 web3
  2. > do
  3. > ssh-copy-id $i
  4. > done

验证SSH免密登录

  1. [root@ansible-server ~]# ssh web1
  2. [root@web1 ~]# exit
  3. [root@ansible-server ~]# ssh web2
  4. [root@web2 ~]# exit
  5. [root@ansible-server ~]# ssh web3
  6. [root@web3 ~]# exit

安装Ansible软件包

  • 安装ansible软件包,由于ansible需要epel源,本实验配置了阿里的epel源和阿里的Base源(Base源用于安装ansible所需依赖),本地的CentOS7镜像源
  1. [root@ansible-server ~]# yum -y install wget #下载wget工具
  2. [root@ansible-server ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里Base源
  3. [root@ansible-server ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo #下载阿里epel源

安装ansible软件包

  1. [root@ansible-server ~]# yum -y install ansible

查看ansible版本信息

  1. [root@ansible-server ~]# ansible --version
  2. ansible 2.9.17

定义Ansible主机清单

  • ansible主配置文件:/etc/ansible/ansible.cfg
  • ansible默认清单文件:/etc/ansible/hosts
  • 编辑清单文件定义主机组
  1. [root@ansible-server ~]# vim /etc/ansible/hosts
  2. [websrvs]
  3. 192.168.0.26
  4. 192.168.0.27
  5. 192.168.0.28

列出指定组内主机列表

  1. [root@ansible-server ~]# ansible websrvs --list-host
  2. hosts (4):
  3. 192.168.0.26
  4. 192.168.0.27
  5. 192.168.0.28

ansible-doc命令介绍:

  • ansible-doc #模块文档命令
  • 常用选项:
    -l #列出所有模块列表
    -s #查看模块帮助信息

    列出模块列表

  1. [root@ansible-server ~]# ansible-doc -l

显示ping模块帮助信息

  1. [root@ansible-server ~]# ansible-doc -s ping

使用ping模块测试websrvs组主机连通性

  1. [root@ansible-server ~]# ansible websrvs -m ping
  • Ansible命令返回值的颜色表示:
    • 绿色:代表对远程节点不进行相应修改,没有发生改变,命令执行成功了
    • 黄色:代表对远程节点进行了相应的修改,命令执行成功了
    • 红色:代表你的命令执行失败或者是有异常,反正就是错误了
    • 粉色:代表命令执行后发出的警告信息,给我们一些建议(可以忽略)
  • Ansible执行命令的方式
    • ad-doc:在命令行执行的命令(临时命令)
    • Playbook:将命令写入到Playbook剧本中

Ansible命令格式介绍

  • 常用命令格式:ansible 组名/主机 [-m 模块名] [-a 模块参数]

Ansible常用模块介绍

command 模块

  • command模块为默认模块,用于远程执行命令(命令模块)
  • 注意:使用command模块在远程主机中执行命令时,不会经过远程主机的shell处理,在使用command模块时,如果需要执行的命令中含比如”<“, “>”, “|”, “;” 和 “&” 这些符号时,这些符号的功能也会失效
  • 常用参数:
    • chdir:此参数表示执行命令之前,会先进入到指定的目录中
    • creates: 此参数表示文件如果存在于远程主机中,则不执行对应命令,如果不存在,才执行
    • removes:此参数表示文件如果不存在于远程主机中,则不执行对应命令,如果存在 ,才执行
  • command模块示例:
  1. #chdir参数表示执行命令之前,会先进入到指定的目录中
  2. [root@ansible-server ~]# ansible websrvs -m command -a 'chdir=/root/ ls'
  3. #creates参数表示如果/etc/passwd文件存在于远程主机中,则不执行对应命令,如果不存在,才执行”touch”命令
  4. [root@ansible-server ~]# ansible websrvs -m command -a 'creates=/etc/passwd touch /opt/passwd'
  5. #演示:creates参数在文件不存在情况下才会执行“touch”命令
  6. [root@ansible-server ~]# ansible websrvs -m command -a 'creates=/opt/passwd touch /opt/passwd'
  7. #removes参数表示如果/opt/abc文件不存在,就不执行“mv”命令,如果文件存在则执行“mv”命令
  8. [root@ansible-server ~]# ansible websrvs -m command -a 'removes=/opt/abc mv /opt/abc /root/'
  9. #演示:removes参数如果/opt/passwd文件不存在,就不执行“mv”命令
  10. [root@ansible-server ~]# ansible websrvs -m command -a 'removes=/opt/passwd mv /opt/passwd /root/'
  11. [root@ansible-server ~]# ansible websrvs -m command -a 'hostname'
  12. [root@ansible-server ~]# ansible websrvs -m command -a 'ip a s ens32'
  13. [root@ansible-server ~]# ansible websrvs -a 'uname -r' #查看内核信息
  14. [root@ansible-server ~]# ansible websrvs -a 'free -h' #查看内存信息

shell 模块

  • shell 模块,远程执行命令模块,和command模块类似,区别在于shell模块通过/bin/bash程序处理命令
  • 常用参数
    • cmd:此参数指定用于执行的命令(用于在Playbook剧本中)
    • chdir:此参数表示执行命令之前,会先进入到指定的目录中
    • creates: 此参数表示文件如果存在于远程主机中,则不执行对应命令,如果不存在,才执行
    • removes:此参数表示文件如果不存在于远程主机中,则不执行对应命令,如果存在 ,才执行

提示: shell模块中chdir、creates、removes参数的作用与command模块中的作用都是相同的,此处不再举例

  • shell 模块示例:
  1. #查看/etc/passwd文件,并通过管道符传递给“wc -l”统计文件行数
  2. [root@ansible-server ~]# ansible websrvs -m shell -a 'cat /etc/passwd | wc -l'
  3. #查看/etc/passwd文件,并通过“>”将文件内容重定向至/opt/passwd文件中
  4. [root@ansible-server ~]# ansible websrvs -m shell -a 'cat /etc/passwd > /opt/passwd'
  5. #通过chdir参数进入/opt/目录,执行“ls”
  6. [root@ansible-server ~]# ansible websrvs -m shell -a 'chdir=/opt/ ls'
  7. #通过chdir参数进入/opt目录,执行“cat”查看passwd文件内容
  8. [root@ansible-server ~]# ansible websrvs -m shell -a 'chdir=/opt/ cat passwd'
  9. #查看主机名
  10. [root@ansible-server ~]# ansible websrvs -m shell -a 'hostname'
  11. #查看内核信息
  12. [root@ansible-server ~]# ansible websrvs -m shell -a 'uname -r'
  13. #查看ens32网卡的IP地址信息
  14. [root@ansible-server ~]# ansible websrvs -m shell -a 'ip a s ens32 | grep inet'
  15. #查看内存使用信息
  16. [root@ansible-server ~]# ansible websrvs -m shell -a 'free -h'
  17. #查看分区使用信息
  18. [root@ansible-server ~]# ansible websrvs -m shell -a 'df -h'
  19. #关闭防火墙&&设置开机不自起
  20. [root@ansible-server ~]# ansible websrvs -m shell -a 'systemctl stop firewalld && systemctl disable firewalld'

script 模块

  • script 模块用于远程执行脚本,脚本存放在ansible主机本地,不需要拷贝到远程主机
  • 常用参数:
    • chdir:此参数表示执行命令之前,会先进入到指定的目录中
    • creates: 此参数表示文件如果存在于远程主机中,则不执行对应命令,如果不存在,才执行命令
    • removes:此参数表示文件如果不存在于远程主机中,则不执行对应命令,如果存在 ,才执行命令

提示: shell模块中chdir、creates、removes参数的作用与command模块中的作用都是相同的,此处不再举例

  • script模块示例:
1.mkdri /mnt/centos
2.mount /dev/cdrom /mnt/centos
3.rm -rf /etc/yum.repos.d/*
4.vim /etc/yum.repos.d/local.repo
[local_file]
name=loal_file
baseurl=fiel:///mnt/centos
enabled=1
gpgcheck=0


#编写搭建yum仓库脚本
[root@ansible-server ~]# vim yum.sh 
#!/bin/bash
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos
echo "/dev/cdrom /mnt/centos iso9660 defaults 0 0" >> /etc/fstab
rm -rf /etc/yum.repos.d/*
echo "[local_centos7]
name=local_centos7
baseurl=file:///mnt/centos
enabled=1
gpgcheck=0" > /etc/yum.repos.d/centos.repo
yum repolist

#使用script模块执行此脚本
[root@ansible-server ~]# ansible websrvs -m script -a '/root/yum.sh'

yum 模块

  • yum 模块,用于在远程主机通过yum源管理软件包
  • 常用参数:
    • name:必须参数,用于指定需要管理的软件包名字
    • state:用于指定软件包的状态
      • present:此状态为默认值,表示安装软件包
      • installed:此状态表示安装软件包,与present等效
      • latest:此状态表示安装yum中最新版本软件包
      • removed:此状态表示删除对应软件包
      • absent:此状态表示删除对应软件包,与removed等效

yum模块示例:

#使用yum模块安装vsftpd软件包(本地yum源默认已经禁用软件包检测)
[root@ansible-server ~]# ansible websrvs -m yum -a 'name=vsftpd'

#卸载vsftpd软件包
[root@ansible-server ~]# ansible websrvs -m yum -a 'name=vsftpd state=removed'

#ftp组内主机安装vsftpd服务
[root@ansible-server ~]# ansible websrvs -m yum -a 'name=vsftpd'

service 模块

  • service 模块,用于管理远程主机的服务,如:启动或停止服务
  • 常用参数:
    • name:此参数用于指定需要操作的服务名称,如 vsftpd
    • state: 此参数用于指定服务的状态
      • started:此状态用于启动服务 ```shell

        启动vsftpd服务

        [root@ansible-server ~]# ansible websrvs -m service -a ‘name=vsftpd state=started’

查看服务状态

[root@ansible-server ~]# ansible websrvs -m shell -a ‘systemctl status vsftpd’


      - **restarted:此状态用于重启服务**
```shell
#重启服务
[root@ansible-server ~]# ansible ftp -m service -a 'name=vsftpd state=restarted'
  - **stopped:此状态用于停止服务**
#停止vsftpd服务
[root@ansible-server ~]# ansible ftp -m service -a 'name=vsftpd state=stopped'
  • enabled:此参数 用于指定是否将服务设置为开机启动项,设置为yes表示将对应服务设置为开机启动,设置为no表示不会开机启动。
    #启动服务并设置服务随机自启
    [root@ansible-server ~]# ansible ftp -m service -a 'name=vsftpd state=started enabled=yes'
    

copy 模块

  • copy 模块,用于将文件复制到远程主机
  • 常用参数:
    • src:此参数用于指定需要拷贝的文件或目录
    • dest:此参数用于指定文件将拷贝到远程主机的哪个目录中,dest为必须参数 ```shell

      在ansible本地主机创建文件

      [root@ansible-server ~]# touch /tmp/test.txt

将本地/tmp/test.txt文件拷贝至ftp组内主机的/var/ftp目录下

[root@ansible-server ~]# ansible ftp -m copy -a ‘src=/tmp/test.txt dest=/var/ftp/‘ [root@ansible-server ~]# ansible ftp -m shell -a ‘ls /var/ftp’


   - **content:此参数当不使用src指定拷贝的文件时,可以使用content直接指定文件内容,src与content两个参数必有其一,否则会报错**
```shell
#使用content参数在远程主机直接创建文件并写入内容
[root@ansible-server ~]# ansible ftp -m copy -a 'content="hello" dest=/var/ftp/test1'

#查看远程主机文件内容
[root@ansible-server ~]# ansible ftp -a 'cat /var/ftp/test1'
  • force:此参数当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变 ```shell

    本地创建test1文件,并写入abc

    [root@ansible-server ~]# echo abc > test1 [root@ansible-server ~]# cat test1

使用force参数指定当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,不执行覆盖

[root@ansible-server ~]# ansible ftp -m copy -a ‘src=/tmp/test1 dest=/var/ftp/test1 force=no’ 192.168.0.25 | SUCCESS => { “changed”: false


   - **backup:此参数当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机**
```shell
#使用backup参数指定当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,对远程主机文件先进行备份
[root@ansible-server ~]# ansible ftp -m copy -a 'src=/root/test1 dest=/var/ftp backup=yes'

#查看远程主机信息
[root@ansible-server ~]# ansible ftp -a 'ls /var/ftp'
...
test1
test1.12778.2021-03-16@00:57:26~  #备份后文件
  • owner:此参数指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错。 ```shell

    创建文件

    [root@ansible-server ~]# touch test2

拷贝test2文件到远程主机,并指定属主为ftp用户

[root@ansible-server ~]# ansible ftp -m copy -a ‘src=/root/test2 dest=/var/ftp/ owner=ftp’

查看文件详细属性信息

[root@ansible-server ~]# ansible ftp -a ‘ls -l /var/ftp/test2’ 192.168.0.29 | CHANGED | rc=0 >> -rw-r—r—. 1 ftp root 6 3月 16 01:07 /var/ftp/test2

可以看到文件的属主以变成ftp用户


   - **group:此参数指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错**
```shell
#创建test3文件
[root@ansible-server ~]# touch test3

#拷贝test3文件到远程主机,并指定属主为ftp用户,所属组为ftp用户基本组
[root@ansible-server ~]# ansible ftp -m copy -a 'src=/root/test3 dest=/var/ftp/ owner=ftp group=ftp'

#查看文件详细属性信息
[root@ansible-server ~]# ansible ftp -a 'ls -l /var/ftp/test3'
192.168.0.29 | CHANGED | rc=0 >>
-rw-r--r--. 1 ftp ftp 0 3月  16 01:16 /var/ftp/test3
  • mode:此参数指定文件拷贝到远程主机后的权限,如果你想将权限设置为”rw-r–r–“,则可以使用mode=0644表示 ```shell

    拷贝test4文件到远程主机,并指定属主为ftp用户,所属组为ftp用户基本组,并指定权限为0744

    [root@ansible-server ~]# ansible ftp -m copy -a ‘src=/root/test4 dest=/var/ftp/ owner=ftp group=ftp mode=0744’

查看文件详细属性信息

[root@ansible-server ~]# ansible ftp -a ‘ls -l /var/ftp/test4’

如果后期需要修改权限可以使用shell模块修改

[root@ansible-server ~]# ansible ftp -m shell -a ‘chmod 755 /var/ftp/test4’ [root@ansible-server ~]# ansible ftp -a ‘ls -l /var/ftp/test4’ 192.168.0.29 | CHANGED | rc=0 >> -rwxr-xr-x. 1 ftp ftp 0 3月 16 01:23 /var/ftp/test4

可以看到,权限已被修改成功


<a name="rvNim"></a>
# Ansible剧本Playbook

<a name="3dRwE"></a>
## Ansible playbook剧本介绍

- **在ansible中,类似”脚本”的文件被称作”剧本”,英文名称为’playbook’ ,用于配置,部署,和管理被控节点**
- **我们只需要把模块按照顺序编排在playbook剧本中,ansible就会按照剧本一步一步的执行,最终达到我们的目的**
- **playbook是由一个或多个”play”组成的列表,当我们在工作中往往需要不止做一件事情的时候,使用playbook会更加适合。**
- **playbook 与ad-doc相比是一种完全不同的运用方式,剧本需要遵循YAML语法格式编写,文件名以”.yaml”或者”.yml”作为文件名后缀**

<a name="YeEny"></a>
## playbook核心元素

- **hosts:执行的远程主机列表’**
- **tasks:任务集**
- **variables:内置变量或自定义变量在playbook中调用**
- **tempaltes 模板,可替换文件中的变量并实现一些简单逻辑的文件**
- **handles 和notify结合使用,由特定条件触发的操作,满足条件方执行,否则不执行**
- **tags标签,指定某条任务执行,用于选择运行playbook中的部分代码。**

<a name="l0kyl"></a>
### 编写第一个Playbook剧本

```shell
#使用ping模块测试远程主机联通性,并在远程主机创建目录
[root@ansible-server ~]# vim ping_websrvs.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
  - name: ping websrvs
    ping:
  - name: mkdir directory test
    shell:
       cmd: mkdir /test

#第一行:playbook剧本以---开头表明yaml格式文件
#第二行:使用”- “作为开头,”- “表示一个列表项,”- “后面使用hosts关键字指定要操作的主机组名,(注意:横杠后面有空格)表示我要在websrvs这组主机上进行操作,在YAML语法中,键值对需要使用冒号作为分隔,而且冒号后边必须还要有一个空格作为分隔
#第三行:remote_user关键字可以指定在进行远程操作时使用哪个用户进行操作
#第四行:tasks关键字是用来指定要执行哪些操作任务,之后的行都属于tasks任务列表中的任务,每个任务都以”- “开头,每个任务都有自己的名字,任务名使用name关键字进行指定

#运行剧本需要使用’ansible-playbook’命令
[root@ansible-server ~]# ansible-playbook ping_websrvs.yml
TASK [Gathering Facts]   ****************************************************************
ok: [192.168.0.28]
ok: [192.168.0.27]
ok: [192.168.0.26]

TASK [ping websrvs] ****************************************************************
ok: [192.168.0.26]
ok: [192.168.0.27]
ok: [192.168.0.28]

TASK [mkdir directory test] ****************************************************************
changed: [192.168.0.28]
changed: [192.168.0.26]
changed: [192.168.0.27]

PLAY RECAP ******************************************************************
192.168.0.26               : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.0.27               : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.0.28               : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Playbook源码部署Nginx的Web服务

[root@ansible-server ~]# vim nginx.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
  - name: Copy nginx
    copy: src=/root/nginx-1.18.0.tar.gz  dest=/tmp
  - name: install Rely
    yum: name=gcc,pcre-devel,openssl-devel,zlib
  - name: unpacek nginx
    shell: tar -xf /tmp/nginx-1.18.0.tar.gz -C /tmp
  - name: install nginx
    shell:  cd /tmp/nginx-1.18.0 && ./configure && make && make install
  - name: Copy index.html
    copy: src=/root/index.html dest=/usr/local/nginx/html
  - name: start nginx
    shell: /usr/local/nginx/sbin/nginx


#--syntax-check 用于检测playbook语法是否正确,如果正确只返回playbook名称
[root@ansible-server ~]# ansible-playbook --syntax-check nginx.yml

playbook: nginx.yml

#--check 用于模拟执行playbook
[root@ansible-server ~]# ansible-playbook --check nginx.yml 

PLAY [websrvs] ****************************************************

TASK [Gathering Facts] *******************************************************************
ok: [192.168.0.28]
ok: [192.168.0.26]
ok: [192.168.0.27]

TASK [Copy nginx] *************************************************
ok: [192.168.0.28]
ok: [192.168.0.27]
ok: [192.168.0.26]

TASK [install Rely] ***********************************************
ok: [192.168.0.26]
ok: [192.168.0.27]
ok: [192.168.0.28]

TASK [unpacek nginx] **********************************************
skipping: [192.168.0.26]
skipping: [192.168.0.28]
skipping: [192.168.0.27]

TASK [install nginx] ******************************************************************
skipping: [192.168.0.26]
skipping: [192.168.0.27]
skipping: [192.168.0.28]

TASK [Copy index.html] ******************************************************************
ok: [192.168.0.27]
ok: [192.168.0.26]
ok: [192.168.0.28]

TASK [start nginx] ******************************************************************
skipping: [192.168.0.26]
skipping: [192.168.0.27]
skipping: [192.168.0.28]

PLAY RECAP ******************************************************************
192.168.0.26               : ok=4    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   
192.168.0.27               : ok=4    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   
192.168.0.28               : ok=4    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   


#使用playbook剧本批量在远程主机源码安装nginx
[root@ansible-server ~]# ansible-playbook nginx.yml 

PLAY [websrvs] ******************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [192.168.0.28]
ok: [192.168.0.27]
ok: [192.168.0.26]

TASK [Copy nginx] ******************************************************************
changed: [192.168.0.28]
changed: [192.168.0.27]
changed: [192.168.0.26]

TASK [install Rely] ******************************************************************
ok: [192.168.0.26]
ok: [192.168.0.27]
ok: [192.168.0.28]

TASK [unpacek nginx] ******************************************************************
changed: [192.168.0.28]
changed: [192.168.0.26]
changed: [192.168.0.27]

TASK [install nginx] *******************************************************************
changed: [192.168.0.26]
changed: [192.168.0.28]
changed: [192.168.0.27]

TASK [Copy index.html] *******************************************************************
changed: [192.168.0.27]
changed: [192.168.0.28]
changed: [192.168.0.26]

TASK [start nginx] ********************************************************************
changed: [192.168.0.27]
changed: [192.168.0.28]
changed: [192.168.0.26]

PLAY RECAP ********************************************************************
192.168.0.26               : ok=7    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.0.27               : ok=7    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.0.28               : ok=7    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

循环,变量,条件判断,角色(部署大型的复杂环境)

Ansible学习文档

https://www.zsythink.net/archives/tag/ansible/page/5

NTP网络时间协议

NTP(Network Time Protocol)网络时间协议基于UDP,用于网络时间同步的协议,使网络中的计算机时钟同步到UTC(世界统一时间),再配合各个时区的偏移调整就能实现精准同步对时功能。

chrony是网络时间协议NTP的实现方式, Chrony是一个开源的自由软件 ,在RHEL7/CentOS7操作系统已经是默认安装服务,它能保持系统时间与NTP时间服务器的时间保持同步,让时间始终保持同步。

软件包:chrony

服务名:chronyd

命令程序:chronyc

配置文件:/etc/chrony.conf

安装chrony程序

#CentOS7/RHEL7以默认安装
[root@localhost ~]# rpm -q chrony
chrony-3.2-2.el7.x86_64

#查看服务运行状态
[root@localhost ~]# systemctl status chronyd

#启动chronyd服务&&设置服务随机期自
[root@localhost ~]# systemctl start chronyd
[root@localhost ~]# systemctl enable chronyd

配置文件介绍

#修改/etc/chrony.conf配置文件
[root@localhost ~]# vim /etc/chrony.conf 
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
#配置NTP时间服务器
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst

# Record the rate at which the system clock gains/losses time.
#记录系统时钟获得/丢失时间的速率至drift文件中
driftfile /var/lib/chrony/drift

# Allow the system clock to be stepped in the first three updates
# if its offset is larger than 1 second.
# 默认情况下,chronyd通过减慢或加快时钟速度来逐渐调整时钟。如果时钟与实际时间偏差太大,则需要很长时间才能纠正错误。这种方法叫做步进时钟(时间跳变)。
# 此处表示如果调整值大于1000秒,则这将使系统时钟步进,但仅在前10个时钟更新中。
makestep 1000 10

# Enable kernel synchronization of the real-time clock (RTC).
# 启用RTC(实时时钟)的内核同步
rtcsync

# Enable hardware timestamping on all interfaces that support it.
#hwtimestamp *

# Increase the minimum number of selectable sources required to adjust
# the system clock.
#minsources 2

# Allow NTP client access from local network.
# 只允许192.168.网段的客户端进行时间同步
#allow 192.168.0.0/16

# Serve time even if not synchronized to a time source.
# NTP服务器不可用时,采用本地时间作为同步标准
#local stratum 10

# Specify file containing keys for NTP authentication.
# 指定包含NTP验证密钥的文件
#keyfile /etc/chrony.keys

# Specify directory for log files.
# 指定日志文件的目录
logdir /var/log/chrony

# Select which information is logged.
#将对系统增益或损耗率的估计值以及所做的任何转换记录的更改记录到名为的文件中tracking.log
#log measurements statistics tracking

常用命令

#查看时间同步源
[root@localhost ~]# chronyc sources -n
210 Number of sources = 4
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* 203.107.6.88                  2   6    17    32   +938us[  -17ms] +/-   24ms
^- time.cloudflare.com           3   6    17    31    +56ms[  +56ms] +/-  163ms
^- ns1.luns.net.uk               2   6    17    30    +26ms[  +26ms] +/-  166ms
^? ntp7.flashdance.cx            0   6     0     -     +0ns[   +0ns] +/-    0ns
字段 说明
M 这表示信号源的模式。^表示服务器,=表示对等方,并#指示本地连接的参考时钟
S 此列指示源的状态。“ *”表示chronyd当前同步到的源。“ +”表示可接受的来源,已与所选来源合并。“-”表示组合算法排除的可接受源。“?” 指示已失去连接性或其数据包未通过所有测试的源。“ x”表示一个时钟,它chronyd认为是虚假行情(其时间与大多数其他来源不一致)。“〜”表示时间似乎变化太大的来源。“?” 启动时也会显示条件,直到从中至少收集了3个样本为止
Name/IP address 这显示了IP源的名称或地址
Stratum 这显示了来源的层次,如其最近收到的样本中所报告的那样。层1表示具有本地连接的参考时钟的计算机。与第1层计算机同步的计算机位于第2层。与第2层计算机同步的计算机位于第3层,依此类推
Poll 这显示轮询源的速率,以秒为单位的间隔的以2为底的对数。因此,值为6表示每64秒进行一次测量。chronyd 根据当前情况自动更改轮询速率
Reach 这显示了源的范围寄存器以八进制数字打印。该寄存器有8位,并在从源接收或丢失的每个数据包上进行更新。值377表示已收到所有最后八次传输的有效回复
LastRx 此列显示多久以前从源接收到最后一个样本。通常以秒为单位。这些信件m,h,d或y表示分钟,小时,天或数年。10年的值表示尚未从此来源接收到任何样本
Last sample 此列显示上次测量时本地时钟与源之间的偏移。方括号中的数字表示实际测得的偏移量。这可以以ns(表示纳秒),us(表示微秒),ms(表示毫秒)或s(表示秒)作为后缀。方括号左侧的数字表示原始测量值,已调整为允许此后施加于本地时钟的任何摆度。+/-指示器后面的数字表示测量中的误差范围。正偏移表示本地时钟位于源时钟之前
#立刻手动同步时间
[root@localhost ~]# chronyc -a makestep
200 OK

#检查时间是否同步
[root@localhost ~]# chronyc tracking
Reference ID    : CB6B0658 (203.107.6.88)  #同步到的服务器ID与IP地址
Stratum         : 3
Ref time (UTC)  : Wed Jun 23 15:26:55 2021
System time     : 0.001027327 seconds fast of NTP time
Last offset     : +0.001285393 seconds
RMS offset      : 0.016554436 seconds
Frequency       : 9.343 ppm slow
Residual freq   : -0.813 ppm
Skew            : 1.096 ppm
Root delay      : 0.038546667 seconds
Root dispersion : 0.000631557 seconds
Update interval : 64.2 seconds
Leap status     : Normal
字段 说明
Reference ID 同步到的服务器ID与IP地址
Stratum 层次:表示带有附加参考时钟的计算机距计算机的跳数。这样的计算机是第1层计算机,因此示例中的计算机距离两跳(也就是说,abc是第2层,并且与第1层同步)
Ref time (UTC) 这是处理来自参考源的最后一次测量的时间(UTC)
System time 在正常操作中,chronyd步进系统时钟,因为时标的任何跳跃都可能对某些应用程序产生不利影响。取而代之的是,通过稍微加快或降低系统时钟的速度来纠正系统时钟中的任何错误,直到错误被消除,然后恢复到系统时钟的正常速度
Last offset 最后偏移:上次时钟更新时本地偏移量
RMS offset 偏移值的长期平均值
Frequency “频率”是如果chronyd不对其进行校正,则系统时钟出错的速率。用ppm(百万分之一)表示。例如,值1 ppm表示当系统时钟认为它已提前1秒时,它实际上已相对于真实时间提前了1.000001秒。
Residual freq 显示了当前选定参考源的“剩余频率”。这反映了来自参考源的测量结果表明该频率应与当前使用的频率之间的任何差异
Skew 频率上的估计误差范围
Root delay 这是到第1层计算机的网络路径延迟的总和,该计算机最终从该第1层计算机同步。根延迟值以纳秒分辨率打印。在某些极端情况下,该值可以为负。(这可能发生在对称的对等方排列中,其中计算机的频率彼此不跟踪,并且相对于每台计算机的周转时间,网络延迟非常短。)
Root dispersion 根扩散:这是通过所有计算机累积到第1层计算机的总色散,最终从第1层计算机对其进行同步。色散是由于系统时钟分辨率,统计测量变化等引起的。根色散值以纳秒分辨率打印
Update interval 更新间隔
Leap status 这是飞跃状态,可以是“正常”,“插入第二”,“删除第二”或“未同步

案例需求

搭建一台NTP服务器,同步阿里云时间,当阿里云不可用时,使用本地时间,其他服务器同步这台服务器上的时间,确保时间一致。

配置服务端

[root@localhost ~]# vim /etc/chrony.conf 
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# 注释其他server开头的配置,添加阿里云NTP公共时间同步服务器
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
#添加阿里NTP服务
server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
#允许所有网段客户端进行时间同步
allow 0.0.0.0/0    
#NTP服务器不可用时,采用本地时间作为同步标准
local stratum 10

#重启chronyd服务
[root@localhost ~]# systemctl restart chronyd

#查看时间同步源
[root@localhost ~]# chronyc sources -n
210 Number of sources = 2
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* 203.107.6.88                  2   6    17    43    -87us[-3038us] +/-   22ms
^+ 120.25.115.20                 2   6    33    41  +4255us[+4255us] +/-   24ms

配置客户端

#查看chrony软件包是否安装
[root@host26 ~]# rpm -q chrony
chrony-3.2-2.el7.x86_64

#修改配置文件/etc/chrony.conf
[root@host26 ~]# vim /etc/chrony.conf 
# 注释其他server开头的配置,添加本地NTP公共时间同步服务器
server 192.168.0.24 iburst

#重启chronyd服务&&设置服务随机自启
[root@host26 ~]# systemctl restart chronyd
[root@host26 ~]# systemctl enable chronyd
[root@host26 ~]# systemctl status chronyd

#查看时间同步源
[root@host26 ~]# chronyc sources -n
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^? 192.168.0.24                  0   7     0     -     +0ns[   +0ns] +/-    0n

#查看系统时间
[root@host26 ~]# date

rsync远程同步

rsync(Remote Sync): 是一款开源,快速,多功能的可实现本地或远程主机数据同步与增量备份的优秀工具。(数据同步与备份的工具)可使本地主机不同分区或目录之间及本地和远程两台主机之间的数据快速同步,远程备份等功能 。

在同步备份时,默认情况下,rsync通过其独特的“quick check”算法,仅同步大小或者最后修改时间发生变化的文件或目录(也可根据权限,属主等变化同步,需要制定参数)。甚至是只同步一个文件里变化的内容部分,所以可以实现快速的同步数据的功能。

提示:传统的cp,scp工具拷贝每次均为完整拷贝,而rsync除了完整拷贝,还具备增量拷贝的功能,因此更加灵活。

rsync特性

1)支持拷贝特殊文件如链接,设备文件等

2)可以有排除指定文件或目录同步的功能

3)可以保持原来文件或目录的权限,时间,软硬链接等所有属性均不改变。

4)可实现增量同步,即只同步发生变化的数据,因此数据传输效率更高

生产场景

1)借助cron定时任务+rsync把所有客户服务器数据同步到备份服务器
2)针对公司重要数据备份混乱状况和领导提出备份全网数据的解决方案
3)通过本地打包备份,然后rsync结合inotify(监控)应用把全网数统一备份到一个固定存储服务器,然后在存储服务器上通过脚本检查并报警管理员备份结果
4)定期将IDC机房的数据备份公司的内部服务器,防止机房地震及火灾问题 导致数据丢失
实时同步,解决存储服务器的单点问题

rsync总结

rsync就是会同步指定的两端目录之间的数据,这个数据可以是特殊的数据。同步之前就先进行两端的数据的比对,只会同步两者之间不同的部分,并保留文件原本的属性。并且支持匿名的方式进行同步传输。所以rsync在备份、同步上就会较为快速。

软件安装

rsync官方地址: http://rsync.samba.org/

安装方式:源码安装、二进制RPM安装

#安装rsync
[root@master ~]# yum -y install rsync

本地同步语法

命令格式1:rsync 选项… 本地目录A 本地目录B #同步整个目录

命令格式2:rsync 选项… 本地目录A/ 本地目录B #只同步目录下的数据

常用选项

选项 作用
-n 测试同步过程,不做实际修改
—delete 删除目标目录下多余的文档
-v 显示详细操作信息
-z 传输过程中启用压缩/解压缩
-a 递归同步,包含目录/字子目录及所有文件、保留符号链接文件、保留文件权限、时间标记、保留文件的属主/属组标记、保留设备文件及其他特殊文件

本地同步

#在本地创建2个目录使用rsync实现数据同步
[root@master ~]# mkdir /test1  /opt/test2

#将/test1目录同步至/opt/test2目录下(同步整个目录)
[root@master ~]# rsync -avz /test1 /opt/test2
sending incremental file list  #发送增量文件列表
test1/

sent 59 bytes  received 20 bytes  158.00 bytes/sec
total size is 0  speedup is 0.00
#sent:发送字节59      
#received:接收字节20          
#158.00:字节/秒
#total:总大小为0
#speedup is:加速值为0.00

#查看目录是否同步成功
[root@master ~]# ls /opt/test2/
test1

#在/test1目录下创建测试文件
[root@master ~]# touch /test1/xx.txt

#同步/test1/目录下的数据至/opt/test2目录下
[root@master ~]# rm -rf /opt/test2/*
[root@master ~]# rsync -avz /test1/ /opt/test2

#查看数据是否同步
[root@master ~]# ls /opt/test2
xx.txt

#在/test1目录下创建新文件验证是否只同步新增加的数据
[root@master ~]# touch /test1/abc.txt
[root@master ~]# ls /test1
abc.txt  xx.txt

#执行同步
[root@master ~]# rsync -avz /test1/ /opt/test2
sending incremental file list
./
abc.txt   #只同步了新增加的文件

sent 130 bytes  received 38 bytes  336.00 bytes/sec
total size is 0  speedup is 0.00

[root@master ~]# ls /opt/test2
abc.txt  xx.txt

#向xx.txt文件增加内容验证同步
[root@master ~]# echo xxoo > /test1/xx.txt 
[root@master ~]# cat /test1/xx.txt 
xxoo

#执行同步
[root@master ~]# rsync -avz /test1/ /opt/test2
sending incremental file list
xx.txt  #只同步变化的文件

sent 135 bytes  received 35 bytes  340.00 bytes/sec
total size is 5  speedup is 0.03

[root@master ~]# cat /opt/test2/xx.txt 
xxoo

#在执行同步时,如果目标目录下的内容发生变化,源目录不会跟着改变
[root@master ~]# cd /opt/test2
[root@master test2]# touch test{1..100}

#执行同步操作
[root@master test2]# rsync -avz /test1/ /opt/test2
sending incremental file list
./   #没有任何的变化,既没同步任何的数据

sent 93 bytes  received 19 bytes  224.00 bytes/sec
total size is 5  speedup is 0.04

#执行同步时,删除目标目录下多余的文件
[root@master test2]# rsync -avz --delete /test1/ /opt/test2

#查看test2目录
[root@master test2]# ls
abc.txt  xx.txt

远程同步语法

命令格式1:rsync 本地目录 用户名@对方IP地址:/目标目录 #同步源目录本身

命令格式2:rsync 本地目录/ 用户名@对方IP地址:/目标目录 #同步源目录下内容

远程同步

#客户端主机安装rsync程序
[root@client ~]# yum -y install rsync

#将本地主机/test1目录下内容同步到其他主机
[root@master ~]# rsync -avz /test1/ root@192.168.0.28:/opt
root@192.168.0.28's password: 
sending incremental file list
./
abc.txt
xx.txt

sent 174 bytes  received 57 bytes  154.00 bytes/sec
total size is 5  speedup is 0.02'

#远程主机查看是否同步成功
[root@client ~]# ls /opt
abc.txt  xx.txt
[root@client ~]# cat /opt/xx.txt 
xxoo

#在本地主机/test1目录下创建文件执行同步
[root@master ~]# touch /test1/test{1..10}
[root@master ~]# ls /test1
abc.txt  test10  test3  test5  test7  test9
test1    test2   test4  test6  test8  xx.txt

[root@master ~]# rsync -avz /test1/ root@192.168.0.28:/opt
root@192.168.0.28's password: 
sending incremental file list
./
test1
test10
test2
test3
test4
test5
test6
test7
test8
test9'

#远程主机验证是否同步成功
[root@client ~]# ls /opt
abc.txt  test10  test3  test5  test7  test9
test1    test2   test4  test6  test8  xx.txt

rsync+inotify实时同步

inotify 是Linux内核用于通知用户空间的程序文件系统变化的机制,如文件增加、删除等事件可以立刻让用户得知。

inotify官方地址:http://download.sf.net/inotify-tools/

环境前准备

#配置同步主机之间ssh免密登录
[root@master ~]# ssh-keygen
[root@master ~]# ssh-copy-id root@192.168.0.28
[root@master ~]# ssh 192.168.0.28
[root@client ~]# exit

源码安装inotify

#安装inotify依赖包(gcc)
[root@master ~]# yum -y install gcc

#解压源码包
[root@master ~]# tar -xf inotify-tools.tar.gz 、
[root@master ~]# cd tools/
[root@master tools]# ls
inotify-tools-3.13.tar.gz  other
[root@master tools]# tar -xf inotify-tools-3.13.tar.gz 
[root@master tools]# cd inotify-tools-3.13
[root@test inotify-tools-3.13]# ./configure  --prefix=/usr/local/inotify  #指定安装路径
[root@test inotify-tools-3.13]# make
[root@test inotify-tools-3.13]# make install
[root@master ~]# ls /usr/local/inotify/
bin  include  lib  share

[root@master ~]# ls /usr/local/inotify/bin
inotifywait(命令)  inotifywatch


#将命令程序链接到PATH路径下,方便后期的使用
[root@master ~]# ln -s /usr/local/inotify/bin/inotifywait /sbin

inotify使用方式

命令格式:inotify 选项 目标文件

常用选项

选项 功能
-m 持续监控,捕获一个事件后不退出
-r 递归监控,包括子目录
-q 减少屏幕输出信息
-e 指定监控的:modify(修改),move(移动、改名),create(创建),delete(删除),attrib(权限)

配置实时监控

#监控本机/test1目录
[root@master ~]# vim rsync.sh 
#!/bin/bash
while inotifywait -rq -e modify,create,delete,attrib /test1/
do
   rsync  -avz --delete  /test1/ root@192.168.0.28:/opt
done


#实现从本地到远程的Web目录推送
#源目标:/var/www/html
#参考脚本
#!/bin/bash
FROM_DIR=“/var/www/html/”
RSYNC_CMD=“rsync –za --delete $FROM_DIR  root@192.168.0.211:/var/www/html”
while inotify –rqq –e modify,move,create,delete,attrib  $FROM_DIR      #q不显示输出
do
$RSYNC_CMD
done  &

image.png

DHCP概述及原理:

DHCP地址分配的四次会话
DISCOVERY -OFFER -REQUEST -ACK

服务端基本概念:

租期:允许客户机组用IP地址的时间期限,单位为秒
作用域:分配给客户机的IP地址所在网段
地址池:用来动态分配的IP地址范围

安装、配置dhcpd服务

  • 软件包:dhcp
  • 服务名:dhcpd
  • ** 配置文件:/etc/dhcp/

PXE+kickstart网络装机平台.pptx

image.png
image.png

日志功能

  • 系统和程序的“记事本”
  • 记录系统和程序运行中发生的各种事件
  • 通过查看日志可以了解信息以及排除故障
  • 日志也是信息安全控制的依据

    内核级系统日志

  • 日志由系统服务rsyslog服务统一记录和管理

  • 日志消息采用文本格式记录
  • 主要记录的信息:事件发生的时间、主机、进程、内容(类似于:时间、地点、人物、发生的事情)
  • 系统日志:/var/log/messages

    常见日志文件介绍

    | 日志文件 | 用途 | | —- | —- | | /var/log/messages | 记录内核信息、各种服务的公共信息 | | /var/log/boot.log | 记录系统启动过程的各种信息 | | /var/log/cron | 记录计划任务(**crond)的相关信息 | | /var/log/maillog | 记录邮件收发的相关信息 | | /var/log/secure | 记录与访问限制相关的安全信息** |

日志分析

  • 通用分析工具:tail、tail -f、less、grep、 awk、sed 等过滤工具等文本浏览/检索命令
  • 专业日志分析工具:Webmin 系统管理套件,Webalizer、AWStats 日志统计套件,ELK 日志分析平台

    日志级别

  • Linux内核定义的事件紧急程度,数值越小越优先

    • 0: emerg #会导致主机系统不可用的情况
    • 1: alert #须马上采取措施解决问题
    • 2: crit #比较严重的情况
    • 3: err #运行出现错误
    • 4: warning #可能会影响系统功能的事件
    • 5: notice #不会影响系统但值得注意
    • 6: info #一般信息
    • 7: debug #程序或系统调试信息

      journalctl工具

  • 使用journalctl工具提取由systemd-journal 服务搜集的日志,主要包括内核/系统日志、服务日志

  • journalctl | grep 关键词
  • journalctl -u 服务名 -p 日志级别
  • journalctl -n 消息条数