- shell概述
- 规范shell脚本组成
- 如何写好一个shell脚本
- 编写脚本
- 脚本的执行方式
- 常用特殊符号补充
- 变量
- read标准输入取值
- 变量种类
- 判断文件状态[ 参数 ]
- 整数比较
- 字符串对比
- 常用数值运算方式
- 字符串判断
- 条件判断结构
- case条件判断结构
- for循环
- while循环
- shell函数
- 脚本中断及退出
- 字符串截取
- 字符串替换
- 字符串掐头去尾
- shell数组
- 正则表达式
- sed流式编辑器
- awk编程语言
- cron周期性计划任务
- SELinux系统内核安全机制
- 环境准备
- 常见协议及端口
- 安全防护firewalld防火墙
- iptables防火墙 ————匹配及停止
- iptables框架
- iptables命令格式
- 主机型防火墙规则配置
- 设置防火墙默认规则
- sudo用户提权
- OpenSSH
scp远程复制工具- 提高ssh服务安全性
- ">

- 文件共享服务FTP介绍
- vsftpd介绍
- NFS网络文件系统
- Apache httpd的web服务
- httpd虚拟web主机
- Ansible自动化运维
- 定义Ansible主机清单
- Ansible命令格式介绍
- Ansible常用模块介绍
- 启动vsftpd服务
- 查看服务状态
- 在ansible本地主机创建文件
- 将本地/tmp/test.txt文件拷贝至ftp组内主机的/var/ftp目录下
- 本地创建test1文件,并写入abc
- 使用force参数指定当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,不执行覆盖
- 创建文件
- 拷贝test2文件到远程主机,并指定属主为ftp用户
- 查看文件详细属性信息
- 可以看到文件的属主以变成ftp用户
- 拷贝test4文件到远程主机,并指定属主为ftp用户,所属组为ftp用户基本组,并指定权限为0744
- 查看文件详细属性信息
- 如果后期需要修改权限可以使用shell模块修改
- 可以看到,权限已被修改成功
- DHCP概述及原理:
shell概述
- shell是一个程序,它连接了用户和Linux内核,它可以解释用户输入的命令传递给内核,让用户可以更加方便的使用Linux系统
- shell 本身并不是内核的一部分,它只是站在内核基础上编写的一个应用程序
- shell具备编程的能力,shell也是一种语言,C,C++,java,Python,Go等
- 语言分为编译型语言,C,C++,Go,需要提前编译,编译语言都有编译器
- 解释型语言,shell,Python,php,不需要提前编译,一边执行,一边编译,每种解释型语言都有解释器
- shell语言支持大部分编程语言都具备的功能:if判断,for循环,变量,数组,函数,加减乘除,逻辑运算
规范shell脚本组成
[root@test ~]# vim user.sh#!/bin/bash(环境声明)#注释信息可执行代码…
如何写好一个shell脚本
- 明确任务需求
- 按需求整理好每一个步骤,先做什么,后做什么
- 运行脚本,并根据运行结果排除错误
- 优化脚本并达到最终效果
编写脚本
编写第一个脚本
[root@localhost ~]# vim hello.sh#!/bin/bash#hello wordecho hello word#赋予执行权限[root@localhost ~]# chmod u+x hello.sh#执行脚本[root@localhost ~]# /root/hello.shhello word
编写创建用户脚本
[root@localhost ~]# vim user.sh#!/bin/bashuseradd abcpasswd abc[root@localhost ~]# chmod u+x user.sh#非交互[root@localhost ~]# vim user.sh#!/bin/bashuseradd yyyyecho 1 | passwd --stdin yyyy[root@localhost ~]# ./user.sh更改用户 yyyy 的密码 。passwd:所有的身份验证令牌已经成功更新。
编写批量查看脚本
#查看系统版本信息,查看系统内核信息,查看系统内存信息,查看系统网卡信息,查看当前主机名[root@localhost ~]# vim info.shcat /etc/redhat-releaseuname -rfree -hifconfig ens32hostname#赋予执行权限[root@localhost ~]# chmod u+x info.sh#执行脚本[root@localhost ~]# ./info.shCentOS Linux release 7.6.1810 (Core)3.10.0-957.el7.x86_64total used free shared buff/cache availableMem: 972M 480M 147M 16M 344M 260MSwap: 2.0G 239M 1.8Gens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255inet6 fe80::8903:cb8:127b:dbc8 prefixlen 64 scopeid 0x20<link>ether 00:0c:29:a0:e8:12 txqueuelen 1000 (Ethernet)RX packets 230110 bytes 325471733 (310.3 MiB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 20635 bytes 1385581 (1.3 MiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0localhost.localdomain
编写配置本地yum源脚本
#编写搭建本地yum仓库脚本【版1,丢人版】[root@localhost ~]# vim yum.sh#!/bin/bashmkdir /mnt/centosmount /dev/cdrom /mnt/centosecho '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstabrm -rf /etc/yum.repos.d/*touch /etc/yum.repos.d/local.repoecho "[local]" > /etc/yum.repos.d/local.repoecho "name=local_centos" >> /etc/yum.repos.d/local.repoecho "baseurl=file:///mnt/centos" >> /etc/yum.repos.d/local.repoecho "enabled=1" >> /etc/yum.repos.d/local.repoecho "gpgcheck=0" >> /etc/yum.repos.d/local.repo#编写搭建本地yum仓库脚本【版2,正常版】[root@localhost ~]# vim yum.sh#!/bin/bashmkdir /mnt/centosmount /dev/cdrom /mnt/centosecho '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstabmount -arm -rf /etc/yum.repos.d/*echo "[local]name=local_centosbaseurl=file:///mnt/centosenabled=1gpgcheck=0" > /etc/yum.repos.d/local.repo#编写搭建本地yum仓库脚本【升级版】[root@localhost ~]# vim yum.sh#!/bin/bashecho "正在配置本地yum仓库..."mkdir /mnt/centosmount /dev/cdrom /mnt/centos &> /dev/nullecho '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstabmount -arm -rf /etc/yum.repos.d/*echo "[local]name=local_centosbaseurl=file:///mnt/centosenabled=1gpgcheck=0" > /etc/yum.repos.d/local.repoecho "本地yum仓库配置以完成..."yum clean all &> /dev/nullecho "仓库软件包数量"yum repolist | tail -1#执行脚本[root@localhost ~]# ./yum.sh正在配置本地yum仓库...本地yum仓库配置以完成...repolist: 4,021仓库软件包数量
脚本的执行方式
- 执行一个脚本的方法有很多种
- 方法一:赋予脚本执行权限后,可用绝对路径或者当前路径执行
- 方法二:调用解释器执行脚本文件
#绝对路径执行脚本[root@localhost ~]# /root/hello.sh#相对路径执行脚本[root@localhost ~]# ./hello.sh#去除执行权限[root@localhost ~]# chmod u-x hello.sh#执行脚本[root@localhost ~]# /root/hello.sh-bash: /root/hello.sh: 权限不够[root@localhost ~]# ./hello.sh-bash: ./hello.sh: 权限不够#调用解释器执行脚本[root@localhost ~]# bash hello.shhello word[root@localhost ~]# cat /etc/shells/bin/sh/bin/bash/usr/bin/sh/usr/bin/bash/bin/tcsh/bin/csh[root@localhost ~]# sh hello.shhello word[root@localhost ~]# tcsh hello.shhello word[root@localhost ~]# csh hello.shhello word
常用特殊符号补充
- “ “ #双引号,引用整体
- ‘ ’ #单引号,引用整体并取消所有特殊字符含义
- $[] #四则运算(+ - * / % 取余数)
- $() #将命令的输出结果作为参数
- #反撇 `` 将命令的输出结果作为参数
#引用整体,不屏蔽特殊符号的功能[root@localhost ~]# echo "$PATH"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin#引用整体,屏蔽特殊符号的功能[root@localhost ~]# echo '$PATH'$PATH#没有特殊符号单引双引都可以[root@localhost ~]# echo "xxoo"xxoo[root@localhost ~]# echo 'xxoo'xxoo#四则运算[root@localhost ~]# echo $[1+1]2[root@localhost ~]# echo $[1+5]6[root@localhost ~]# echo $[10-5]5[root@localhost ~]# echo $[10*5]50[root@localhost ~]# echo $[10/5]2[root@localhost ~]# echo $[1+3+4+5+7]20[root@localhost ~]# echo $[10/3]3[root@localhost ~]# echo $[10%3]1#$()取命令结果作为参数root@localhost ~]# touch $(date +%F)-abc.txt2021-05-09-abc.txt#``取命令结果作为参数[root@localhost ~]# touch `date +%F`-xxoo.txt2021-05-09-xxoo.txt
变量
- 以固定的名称存放可能变化的值,提高脚本的灵活度来适应多变的环境
- 定义变量:变量名=变量值,如:a1=abc(等号两边不要有空格)
- 取消变量:unset 变量名
- 定义变量注意事项:
- 变量名由字母/数字/下划线组成,区分大小写,不能以数字开头,不要使用命令和特殊符号
- 若指定的变量名已经存在,相当于为此变量重新赋值
root@localhost ~]# xx=haha[root@localhost ~]# echo $xxhaha[root@localhost ~]# xx=abcd[root@localhost ~]# echo $xxabcd[root@localhost ~]# xx=5[root@localhost ~]# echo $xx5[root@localhost ~]# echo $[xx+5]10#通过变量定义用户名[root@localhost ~]# vim user.sh#!/bin/bashuser=wangxinuseradd $userecho 1 | passwd --stdin $user[root@localhost ~]# ./user.sh更改用户 wangxin 的密码 。passwd:所有的身份验证令牌已经成功更新。[root@localhost ~]# vim user.sh#!/bin/bashuser=sdduseradd $userecho 1 | passwd --stdin $user[root@localhost ~]# ./user.sh更改用户 sdd 的密码 。passwd:所有的身份验证令牌已经成功更新。[root@localhost ~]# vim user.sh#!/bin/bashuser=panghuuseradd $userecho "用户$user创建成功"echo 1 | passwd --stdin $user &> /dev/nullecho "用户$user密码设置成功"[root@localhost ~]# ./user.sh用户panghu创建成功用户panghu密码设置成功
read标准输入取值
- read 读取用户在键盘上输入的内容,并把内容存放在变量里,可以降低脚本的使用难度
- 命令格式:read -p “提示信息” 变量名
[root@localhost ~]# vim user.sh#!/bin/bashread -p '请输入用户名:' useruseradd $userecho "用户$user创建成功"read -p '请设置用户密码:' passecho $pass | passwd --stdin $user &> /dev/nullecho "用户$user密码设置成功"[root@localhost ~]# ./user.sh请输入用户名:wuhan用户wuhan创建成功请设置用户密码:1用户wuhan密码设置成功[root@localhost ~]# ./user.sh请输入用户名:liangjing用户liangjing创建成功请设置用户密码:xxoo用户liangjing密码设置成功
变量种类
- 环境变量:变量名一般都大写,用来设置用户/系统环境
- 位置变量:bash内置,存储执行脚本时提供的命令参数
- 预定义变量:bash内置,可直接调用的特殊值,不能直接修改
- 自定义变量:用户自定义
- env 命令查看系统所有环境变量
- set 命令查看系统所有变量,包括用户自定义变量
- 环境变量
[root@localhost etc]# envMAIL=/var/spool/mail/rootPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/binPWD=/rootLANG=zh_CN.UTF-8SELINUX_LEVEL_REQUESTED=HISTCONTROL=ignoredupsSHLVL=1HOME=/rootLOGNAME=rootXDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/shareSSH_CONNECTION=192.168.0.1 51791 192.168.0.100 22LESSOPEN=||/usr/bin/lesspipe.sh %sXDG_RUNTIME_DIR=/run/user/0DISPLAY=localhost:10.0_=/usr/bin/envOLDPWD=/root#获取变量值[root@localhost etc]# echo $SHELL/bin/bash[root@localhost ~]# echo $PWD/root#查看系统所有变量[root@localhost ~]# set[root@localhost ~]# set | grep $a
- 位置变量
$0 #脚本名称
$1 #第一个参数
$2 #第二个参数
$3 #第三个参数
$4 #第四个参数
$n… #第n个参数 - 预定义变量
$0 #代表脚本本身
$* #显示所有参数内容
$# #显示有多少个参数
$? #显示上一条命令的执行结果(0代表正确,非0代表错误)[root@localhost ~]# vim test.sh#!/bin/bashecho $0echo $1echo $2echo $3echo $*echo $#echo $$echo $?#赋予执行权限,执行脚本[root@localhost ~]# ./test.sh xx oo dd./test.sh $0xx $1oo $2dd $3xx oo dd $*3 $#15594 $$0 $?
判断文件状态[ 参数 ]
- -e #判断文档(文件/目录)是否存在,存在为真
- -d #判断目录是否存在,存在为真
- -f #判断文件是否存在,存在为真
- -r #可读为真
- -w #可写为真
- -x #可执行为真
#判断文档是否存在[root@localhost ~]# [ -e /etc/ ][root@localhost ~]# echo $?0 #为真#判断目录是否存在[root@localhost ~]# [ -d /opt ][root@localhost ~]# echo $?0[root@localhost ~]# [ -d /etc/passwd ][root@localhost ~]# echo $?1[root@localhost ~]# [ -f /etc/passwd ][root@localhost ~]# echo $?0#判断是否可读(以当前用户身份判断)[root@localhost ~]# [ -r /etc/passwd ][root@localhost ~]# echo $?0#判断是否可写[root@localhost ~]# [ -w /etc/passwd ][root@localhost ~]# echo $?0#判断是否可执行[root@localhost ~]# [ -x /etc/passwd ][root@localhost ~]# echo $?1[root@localhost ~]# ll /etc/passwd-rw-r--r--. 1 root root 3294 5月 9 16:43 /etc/passwd
整数比较
- -gt 大于
- -ge 大于等于
- -eq 等于
- -lt 小于
- -le 小于等于
- -ne 不等于
[root@localhost ~]# [ 1 -gt 1 ][root@localhost ~]# echo $?1[root@localhost ~]# [ 1 -eq 1 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 1 -ge 1 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 1 -ge 2 ][root@localhost ~]# echo $?1[root@localhost ~]# [ 1 -lt 2 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 1 -le 2 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 1 -le 10 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 10 -le 10 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 1 -ne 2 ][root@localhost ~]# echo $?0[root@localhost ~]# [ 2 -ne 2 ][root@localhost ~]# echo $?1
字符串对比
- == 相等
- != 不相等
[root@localhost ~]# [ root == xxoo ][root@localhost ~]# echo $?1[root@localhost ~]# [ root == $USER ][root@localhost ~]# echo $?0[root@localhost ~]# [ $USER == root ][root@localhost ~]# echo $?0[root@localhost ~]# [ abc == bcd ][root@localhost ~]# echo $?1[root@localhost ~]# [ abc != bcd ][root@localhost ~]# echo $?0[root@localhost ~]# [ $USER != root ][root@localhost ~]# echo $?1
常用数值运算方式
- $[] #四则运算(+ - * / % 取余数)
- $(()) #数值运算工具
- expr #数值运算工具
- let #数值运算工具
[root@localhost ~]# echo $[10+5]15[root@localhost ~]# echo $[10-5]5[root@localhost ~]# echo $[10*5]50[root@localhost ~]# echo $[10/5]2[root@localhost ~]# echo $[10%3]1#$(())做数值运算[root@localhost ~]# echo $((10+5))15[root@localhost ~]# echo $((10-5))5[root@localhost ~]# echo $((10*5))50[root@localhost ~]# echo $((10/5))2[root@localhost ~]# echo $((10%3))1#expr做数值运算[root@localhost ~]# echo expr 2+3expr 2+3[root@localhost ~]# echo `expr 2+3`2+3#要求每一部分都要有空格[root@localhost ~]# echo `expr 2 + 3`5[root@localhost ~]# echo `expr 10 - 3`7#当进行乘法运算时,需要实用“\”转义掉*的特殊功能[root@localhost ~]# echo `expr 10 * 3`expr: 语法错误[root@localhost ~]# echo `expr 10 \* 3`30[root@localhost ~]# echo `expr 10 / 3`3#let做数值运算[root@localhost ~]# let 1+1#需要将运算的结果赋予一个变量存储[root@localhost ~]# let x=1+1[root@localhost ~]# echo $x2[root@localhost ~]# let a=10+5[root@localhost ~]# echo $a15#通过变量的值进行运算[root@localhost ~]# let b=a+x[root@localhost ~]# echo $b17#let简写表达式 #let完整表达式let i++ let i=i+1[root@localhost ~]# i=10[root@localhost ~]# let i++[root@localhost ~]# echo $i11let i-- let i=i-1[root@localhost ~]# let i--[root@localhost ~]# echo $i10let i+=2 let i=i+2[root@localhost ~]# let i+=2[root@localhost ~]# echo $i12let i-=2 let i=i-2[root@localhost ~]# let i-=2[root@localhost ~]# echo $i10let i*=2 let i=i*2[root@localhost ~]# let i*=2[root@localhost ~]# echo $i20let i/=2 let i=i/2[root@localhost ~]# let i/=2[root@localhost ~]# echo $i10let i%=2 let i=1%2[root@localhost ~]# let i%=3[root@localhost ~]# echo $i1
字符串判断
- -z #字符串的值为空为真
- -n #字符串的值非空为真(相当于 ! -z)
#判断文件为空为真[root@localhost ~]# [-z /etc/passwd]bash: [-z: 未找到命令...#判断时每一部分要有空格[root@localhost ~]# [ -z /etc/passwd ][root@localhost ~]# echo $?1#判断文件非空为真[root@localhost ~]# [ -n /etc/passwd ][root@localhost ~]# echo $?0[root@localhost ~]# [ -z $i ][root@localhost ~]# echo $?1[root@localhost ~]# [ -n $i ][root@localhost ~]# echo $?0[root@localhost ~]# [ ! -z $i ][root@localhost ~]# echo $?0
条件判断结构
- 当条件满足时执行什么操作,当条件不满足时执行什么操作
- && #逻辑与(并且)
- || #逻辑或(或者)
- ; #条件之间没有逻辑关系
A && B #当A命令执行成功后才会执行B,如果A执行失败则B不执行#判断存在且是文件执行拷贝操作(并且关系)[root@localhost ~]# [ -f /etc/passwd ] && cp /etc/passwd /opt[root@localhost ~]# ls /optabc.tar.bz2 passwd#第一条命令执行失败,后边命令不执行[root@localhost ~]# [ -f /etc/xxoo ] && cp /etc/passwd /opt[root@localhost ~]# [ -f /etc/xxoo ] && cp /etc/xxoo /opt[root@localhost ~]# ls /optA || B #当A命令执行失败后才会执行B,如果A执行成功则B不执行#前便命令执行失败,后边命令则执行[root@localhost ~]# [ -f /etc/xxoo ] || touch /opt/xxoo.txt[root@localhost ~]# ls /optabc.tar.bz2 passwd xxoo.txt#前边命令执行成功,后便命令则不执行[root@localhost ~]# [ -f /etc/fstab ] || touch /opt/fs.txt[root@localhost ~]# ls /optA ; B #执行A命令后执行B,两者没有逻辑关系[root@localhost ~]# touch /mnt/xx.txt ; touch /opt/xx.txt[root@localhost ~]# ls /mntcentos xx.txt[root@localhost ~]# ls /optabc.tar.bz2 abc.txt fs.txt pass.txt passwd xxoo.txt xx.txt[root@localhost ~]# touch /opt/oo.txt ; rm -rf /opt/*[root@localhost ~]# ls /opt[root@localhost ~]# touch /opt/oo.txt ; rm -rf /opt/* ; touch /opt/xx.txt ; rm -rf /mnt/xx.txt[root@localhost ~]# ls /optxx.txt[root@localhost ~]# ls /mnt/
if 条件判断结构
- if 单分支语句,只能判断对,不能判断错
#第一种语法结构if [条件判断];then条件成立时,执行的命令fi#第二种语法结构if [条件判断]then条件成立时,执行的命令fi#if单分支示例[root@localhost yunwei]# vim if1.sh#!/bin/bashif [ -n /etc/passwd ];thenecho "非空"fi[root@localhost yunwei]# chmod u+x if1.sh[root@localhost yunwei]# ./if1.sh非空#只能判断对,不能判断错[root@localhost yunwei]# vim if1.sh#!/bin/bashif [ -z /etc/passwd ];thenecho "非空"fi
if 双分支语句
if [条件判断];then条件成立时,执行命令aelse条件不成立时,执行命令bfi#if双分支示例[root@localhost yunwei]# vim if2.sh#!/bin/bashif [ -z /etc/passwd ];thenecho '空值'elseecho '非空'fi[root@localhost yunwei]# chmod u+x if2.sh[root@localhost yunwei]# ./if2.sh非空#编写参数字的脚本,让计算机产生一个0-9随机数#$RANDOM环境变量,里边存放的是0-65535之间的随机数[root@localhost yunwei]# echo $RANDOM28484[root@localhost yunwei]# echo $RANDOM5440[root@localhost yunwei]# echo $RANDOM29651[root@localhost yunwei]# echo $RANDOM21747[root@localhost yunwei]# echo $RANDOM24494#实用$RANDOM的值对10取余[root@localhost yunwei]# echo $[RANDOM%10]4[root@localhost yunwei]# echo $[RANDOM%10]2[root@localhost yunwei]# echo $[RANDOM%10]5[root@localhost yunwei]# echo $[RANDOM%10]3[root@localhost yunwei]# echo $[RANDOM%10]9[root@localhost yunwei]# echo $[RANDOM%10]1[root@localhost yunwei]# echo $[RANDOM%10]0[root@localhost yunwei]# echo $[RANDOM%10]3[root@localhost yunwei]# echo $[RANDOM%10]2#编写猜数字脚本[root@localhost yunwei]# vim if3.sh#!/bin/bashread -p '请输入0-9之间的随机数:' numnum1=$[RANDOM%10]if [ $num -eq $num1 ];thenecho "恭喜你才对了,奖励一个哇塞女孩!"elseecho "猜错了,请继续努力,奖品是一个哇塞女孩!"echo "正确的结果为$num1"fi[root@localhost yunwei]# chmod u+x if3.shroot@localhost yunwei]# ./if3.sh请输入0-9之间的随机数:1猜错了,请继续努力,奖品是一个哇塞女孩!正确的结果为6[root@localhost yunwei]# ./if3.sh请输入0-9之间的随机数:7猜错了,请继续努力,奖品是一个哇塞女孩!正确的结果为3[root@localhost yunwei]# ./if3.sh请输入0-9之间的随机数:3猜错了,请继续努力,奖品是一个哇塞女孩!正确的结果为2[root@localhost yunwei]# ./if3.sh请输入0-9之间的随机数:0猜错了,请继续努力,奖品是一个哇塞女孩!正确的结果为5[root@localhost yunwei]# ./if3.sh请输入0-9之间的随机数:9猜错了,请继续努力,奖品是一个哇塞女孩!正确的结果为2[root@localhost yunwei]# ./if3.sh请输入0-9之间的随机数:5猜错了,请继续努力,奖品是一个哇塞女孩!正确的结果为7#安装软件包脚本root@localhost yunwei]# vim if4.sh#!/bin/bashif [ `rpm -q vsftpd &> /dev/null ; echo $?` -eq 0 ];thensystemctl start vsftpdsystemctl enable vsftpd &> /dev/nullecho "软件包以安装,并设置随机自启"elseyum -y install vsftpd &> /dev/nullsystemctl start vsftpdsystemctl enable vsftpd &> /dev/nullecho "软件包以重新安装上,并设置随机自启"fi[root@localhost yunwei]# chmod u+x if4.sh[root@localhost yunwei]# ./if4.sh软件包以重新安装上,并设置随机自启
if 多分支语句
if [条件判断1];then条件1成立时,执行命令aelif [条件判断2];then条件2成立时,执行命令belif [条件判断3];then条件3成立时,执行命令c...省略更多条件else所有条件都不成立时,执行命令dfi#编写判断成绩脚本[root@localhost yunwei]# vim if5.sh#!/bin/bashread -p "请输入你的成绩(满分为100分):" numif [ $num -ge 90 ];thenecho "成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩"elif [ $num -ge 80 ];thenecho "比较优秀"elif [ $num -ge 70 ];thenecho "一般一般"elif [ $num -ge 60 ];thenecho "勉强及格"elseecho "收拾收拾,回家种地去吧!"fi[root@localhost yunwei]# chmod u+x if5.sh[root@localhost yunwei]# ./if5.sh请输入你的成绩:66勉强及格[root@localhost yunwei]# ./if5.sh请输入你的成绩:55收拾收拾,回家种地去吧![root@localhost yunwei]# ./if5.sh请输入你的成绩:0收拾收拾,回家种地去吧![root@localhost yunwei]# ./if5.sh请输入你的成绩:99成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩[root@localhost yunwei]# vim if5.sh[root@localhost yunwei]# ./if5.sh请输入你的成绩(满分为100分):100成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩[root@localhost yunwei]# ./if5.sh请输入你的成绩(满分为100分):90成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩[root@localhost yunwei]# ./if5.sh请输入你的成绩(满分为100分):200成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
case条件判断结构
- case从变量中取值,如果变量中的值与预设的值匹配,则执行对应的命令
#case语法结构case $变量名 in值1)执行的命令xx;; #如果变量中的值等于值1,则执行的命令值2)执行的命令yy;; #如果变量中的值等于2,则执行的命令...省略其他分支*)执行的命令zz;; #如果变量中的值都不是以上的值,则执行的命令esac[root@localhost yunwei]# vim case.sh#!/bin/bashread -p "请输入您喜爱的老师(仓老师|波多老师|小泽老师):" xxoocase $xxoo in仓老师)echo "又白又嫩又水润,上楼右转1号房间!";;波多老师)echo "前凸后翘,波涛汹涌,上楼右转2号房间!";;小泽老师)echo "肤白貌美大长腿,上楼右转3号房间!";;*)echo "老师休假了";;esac[root@localhost yunwei]# chmod u+x case.sh[root@localhost yunwei]# ./case.sh请输入您喜爱的老师(仓老师|波多老师|小泽老师):仓老师又白又嫩又水润,上楼右转1号房间![root@localhost yunwei]# ./case.sh 波多老师请输入您喜爱的老师(仓老师|波多老师|小泽老师):波多老师前凸后翘,波涛汹涌,上楼右转2号房间![root@localhost yunwei]# ./case.sh请输入您喜爱的老师(仓老师|波多老师|小泽老师):小泽老师肤白貌美大长腿,上楼右转3号房间![root@localhost yunwei]# ./case.sh请输入您喜爱的老师(仓老师|波多老师|小泽老师):穆穆老师老师休假了
for循环
- for循环处理,根据变量的取值,重复执行xx命令
#for循环语法结构for 变量名 in 值1 值2 值3 值N...do执行的命令done#编写循环创建用户脚本[root@localhost yunwei]# vim user.sh#!/bin/bashfor user in xiaofang xiaowei jiumei aliandouseradd $userecho "$user 创建成功"echo 1 | passwd --stdin $user &> /dev/nullecho "$user 密码设置成功,初始密码为“1”"done[root@localhost yunwei]# chmod u+x user.sh[root@localhost yunwei]# ./user.shuseradd:用户“xiaofang”已存在xiaofang 创建成功xiaofang 密码设置成功,初始密码为“1”xiaowei 创建成功xiaowei 密码设置成功,初始密码为“1”jiumei 创建成功jiumei 密码设置成功,初始密码为“1”alian 创建成功alian 密码设置成功,初始密码为“1”#测试企业的服务器联通性#!/bin/bashfor i in `seq 254`doping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null #-c ping几次 -i ping延迟时间 -w ping超时时间if [ $? -eq 0 ];thenecho "192.168.0.$i UP"elseecho "192.168.0.$i DOWN"fidone[root@localhost yunwei]# chmod u+x ping.sh[root@localhost yunwei]# ./ping.sh#问题:如何将ping的命令结果存储到文件当中,正确的输出结果与错误的输出结果分别单独存储#!/bin/bashecho "请耐心等待!正在进行ping测试!"for i in `seq 4`doping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null #-c ping几>次 -i ping延迟时间 -w ping超时时间if [ $? -eq 0 ];thenecho "192.168.0.$i UP" &>> /opt/ping_up.txtelseecho "192.168.0.$i DOWN" &>> /opt/ping_done.txtfidoneecho "记录完成!"
while循环
- 死循环,只要条件成立就重复执行命令
#while循环语法结构while 条件判断do执行的命令done#编写while循环脚本[root@localhost yunwei]# vim while.sh#!/bin/basha=1while [ $a -le 5 ]doecho $adone[root@localhost yunwei]# chmod u+x while.sh#指定循环的固定次数[root@localhost yunwei]# vim while.sh#!/bin/basha=1while [ $a -le 5 ]doecho $alet a++sleep 0.1done#使用while循环编写猜数字脚本[root@localhost yunwei]# vim while1.sh#!/bin/bashnum=$[RANDOM%10]while :doread -p "请输入0-10之间的数字:" num1if [ $num -eq $num1 ];thenecho "恭喜你才对了,奖励一个绝世容颜哇塞女孩!"exit #退出脚本elseecho "请继续努力,离哇塞女孩还差一步了,加油!"fidone#利用while循环监控网卡进出口流量[root@localhost ~]# vim net_ens32.sh#!/bin/bashwhile :doclear #清屏ifconfig ens32 | head -2 #显示网卡头两行信息ifconfig ens32 | grep "RX p" #网卡入口流量ifconfig ens32 | grep "TX p" #网卡出口流量sleep 0.2 #休眠0.2秒done#使用while循环编写一个测试整个网段IP地址的联通性脚本#!/bin/bashecho "请耐心等待,正在进行ping测试!"i=1while [ $i -le 4 ]doping -c2 -i0.1 -W1 192.168.0.$i &> /dev/nullif [ $? -eq 0 ];thenecho "192.168.0.$i UP" &>> /opt/ping_up.txtelseecho "192.168.0.$i DOWN" &>> /opt/ping_done.txtfilet i++doneecho "记录完成!"~
shell函数
- 在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可称为函数(给一堆命令取一个别名)
- 函数可以使脚本中的代码更加简洁,增强易读性,提高脚本的执行效率
#函数定义格式1function 函数名 {执行的命令1执行的命令2...省略更多命令}#函数定义格式2函数名() {执行的命令1执行的命令2...省略更多命令}#定义函数[root@localhost ~]# net_ens32() {> ifconfig ens32 | head -2> ifconfig ens32 | grep "RX p"> ifconfig ens32 | grep "TX p"> }#调用函数[root@localhost ~]# net_ens32ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255RX packets 2337 bytes 178268 (174.0 KiB)TX packets 2686 bytes 467232 (456.2 KiB)#定义函数[root@localhost ~]# myinfo() {> hostname # 用户名> cat /etc/redhat-release # Linux版本> uname -r #内核版本> free -h # 查看内存使用情况> df -h / #查看分区的使用情况> }#调用函数[root@localhost ~]# myinfolocalhostCentOS Linux release 7.6.1810 (Core)3.10.0-957.el7.x86_64total used free shared buff/cache availableMem: 972M 393M 193M 13M 385M 374MSwap: 2.0G 0B 2.0G文件系统 容量 已用 可用 已用% 挂载点/dev/mapper/centos-root 56G 5.2G 51G 10% /#fork炸弹[root@localhost yunwei]# vim fork.sh#!/bin/bash.() {.|. &}.[root@localhost yunwei]# chmod u+x fork.sh[root@localhost yunwei]# ./fork.sh
脚本中断及退出
- break #结束整个循环
- continue #结束本次循环,进入下一次循环
- exit #退出脚本
#结束第三次循环,进入下一次循环#!/bin/bashfor i in {1..5}do[ $i -eq 3 ] && continueecho $idoneecho Over[root@localhost yunwei]# ./for1.sh1245Over#结束整个循环#!/bin/bashfor i in {1..5}do[ $i -eq 3 ] && breakecho $idoneecho Over[root@localhost yunwei]# ./for1.sh12Over#直接退出脚本[root@localhost yunwei]# vim for1.sh#!/bin/bashfor i in {1..5}do[ $i -eq 3 ] && exitecho $idoneecho Over[root@localhost yunwei]# ./for1.sh12
字符串截取
- 在使用shell脚本完成各种运维任务时,一旦涉及到判断、条件测试等相关操作时往往需要对相关的命令输出进行过滤,提取出符合要求的字符串
- 字符串截取的常用方法:${变量名:起始位置:长度}
- ${}截取字符串时,起始位置是从0开始的
[root@localhost yunwei]# phone=13812345678[root@localhost yunwei]# echo $phone13812345678#统计变量的个数[root@localhost yunwei]# echo ${#phone}11#截取变量的前三位,在截取时包含数字本身:13812345678[root@localhost yunwei]# echo ${phone:0:3}138#截取后四位[root@localhost yunwei]# echo ${phone:7:4}5678#截取中间四位[root@localhost yunwei]# echo ${phone:3:4}1234#截取一个随机的8位密码[root@localhost yunwei]# vim mima.sh#!/bin/bashx=qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789for i in {1..8}don=$[RANDOM%62]p=${x:n:1}pass=$pass$pdoneecho $pass[root@localhost yunwei]# ./mima.sh42iVW9Ba[root@localhost yunwei]# ./mima.shXuEcVGoR
字符串替换
- 只替换第一个匹配的结果:${变量名/xx/yy}
- 替换全部匹配的结果:${变量名//xx/yy}
#只替换匹配到的第一个字符[root@localhost yunwei]# echo $phone13812345678#将匹配到的第一个3替换成4[root@localhost yunwei]# echo ${phone/3/4}14812345678#将匹配到的所有3替换成4[root@localhost yunwei]# echo ${phone//3/4}14812445678
字符串掐头去尾
- 从左向右,最短匹配删除:${变量名#*关键词}
- 从左向右,最长匹配删除:${变量名##*关键词}
- 从右向左,最短匹配删除:${变量名%关键词*}
- 从右向左,最长匹配删除:${变量名%%关键词*}
#定义素材[root@localhost yunwei]# x=`head -1 /etc/passwd`[root@localhost yunwei]# echo $xroot:x:0:0:root:/root:/bin/bash#从左到右最短匹配[root@localhost yunwei]# echo ${x#root}:x:0:0:root:/root:/bin/bash#从左到右最短匹配,不加*只匹配最左侧的字串[root@localhost yunwei]# echo ${x#0}root:x:0:0:root:/root:/bin/bash#从左到右最短匹配,加*匹配遇到的第一个字串[root@localhost yunwei]# echo ${x#*0}:0:root:/root:/bin/bash#从左到右最长匹配[root@localhost yunwei]# echo ${x##0}root:x:0:0:root:/root:/bin/bash#从左到右最长匹配[root@localhost yunwei]# echo ${x##*0}:root:/root:/bin/bash#从右到做最短匹配[root@localhost yunwei]# echo ${x%/bash}root:x:0:0:root:/root:/bin#从右到做最短匹配[root@localhost yunwei]# echo ${x%root*}root:x:0:0:root:/#从右向左最长匹配[root@localhost yunwei]# echo ${x%%root*}#从右向左最短匹配[root@localhost yunwei]# echo ${x%0*}root:x:0:#从右向左最长匹配[root@localhost yunwei]# echo ${x%%0*}root:x:#把文件以.doc结尾的扩展名,全部改为.txt[root@localhost yunwei]# touch {1..100}.doc[root@localhost yunwei]# ls100.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.sh10.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.sh11.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.sh12.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.sh13.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.sh14.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.sh15.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.sh16.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#字符串去尾方式批量修改文件扩展名[root@localhost yunwei]# vim file.sh#!/bin/bashfor i in `ls *.doc`domv $i ${i%doc}txtdone#字符串替换方式批修改文件扩展名[root@localhost yunwei]# vim file.sh#!/bin/bashfor i in `ls *.txt`domv $i ${i/txt/doc}done
shell数组
#定义数组方式一:数组名=(值1 值2 值3 .. .. 值n)[root@localhost yunwei]# x=(11 22 33 44 55 abc)[root@localhost yunwei]# echo $x11#按照下标取值,下标从0起使,0就是数据内的第一个值[root@localhost yunwei]# echo ${x[0]}11[root@localhost yunwei]# echo ${x[0]}11[root@localhost yunwei]# echo ${x[1]}22[root@localhost yunwei]# echo ${x[2]}33[root@localhost yunwei]# echo ${x[3]}44[root@localhost yunwei]# echo ${x[4]}55#获取数组内所有值[root@localhost yunwei]# echo ${x[@]}11 22 33 44 55 abc#定义数组方式二:数组名[下标]=值[root@localhost yunwei]# b[0]=aa[root@localhost yunwei]# b[1]=xx[root@localhost yunwei]# b[2]=xxoo[root@localhost yunwei]# echo ${b[0]}aa[root@localhost yunwei]# echo ${b[1]}xx[root@localhost yunwei]# echo ${b[2]}xxoo[root@localhost yunwei]# echo ${b[@]}aa xx xxoo[root@localhost yunwei]# echo ${b[*]}aa xx xxoo
正则表达式
- 正则表达式使用一串符号描述有共同属性的数据 | 基本正则符号 | 描述 | | —- | —- | | ^ | 匹配行首 | | $ | 匹配行尾 | | [] | 集合,匹配集合中的任意单个字符 | | [^] | 对集合取反 | | . | 匹配任意单个字符 | | * | 匹配前一个字符出现的任意次数[*不允许单独[使用] | | {n,m} | 匹配前一个字符 n 到 m 次 | | {n} | 匹配前一个字符 n 次 |
#匹配以什么什么开头的行[root@localhost yunwei]# grep "^root" /etc/passwdroot:x:0:0:root:/root:/bin/bash[root@localhost yunwei]# grep "^#" /etc/fstab#匹配以什么什么结尾的行[root@localhost yunwei]# grep "bash$" /etc/passwd[root@localhost yunwei]# grep -v "^#" /etc/fstab[root@localhost yunwei]# grep -v "^#" /etc/fstab | grep -v "^$"#集合,匹配集合中的任意单个字符[root@localhost yunwei]# grep "ro[abcotabcd]" /etc/passwd#集合,对集合中的任意单个字符取反[root@localhost yunwei]# grep "ro[^abcotabcd]" /etc/passwd#匹配任意单个字符[root@localhost yunwei]# grep "roo." /etc/passwd[root@localhost yunwei]# grep ".oot" /etc/passwd[root@localhost yunwei]# grep "w.*" /etc/passwd#准备素材[root@localhost yunwei]# vim 1.txtababaabacbadbamnbamnbmnbmnbaaaabaaaaaaabaaaaaaaaaaaaabaabb the ccddabcthethexxooxxootheooxx[root@localhost yunwei]# grep "a*b" 1.txt[root@localhost yunwei]# grep "a.*b" 1.txt #任意所有[root@localhost yunwei]# grep ".*b" 1.txt[root@localhost yunwei]# grep "a.*" 1.txt#匹配前一个字符至少出现一次以上,\{n,m\}[root@localhost yunwei]# grep "a\{1,\}" 1.txt#匹配前一个字符 n 次,\{n\}[root@localhost yunwei]# grep "o\{2\}" /etc/passwd[root@localhost yunwei]# grep "a\{2\}" 1.txt
| 扩展正则符号 | 描述 |
|---|---|
| + | 最少匹配一次 |
| ? | 最多匹配一次 |
| {n,m} | 匹配 n 到 m 次 |
| () | 组合为整体,保留(复制) |
| | | 或者 |
| \b | 单词边界 |
#基本正则用法[root@localhost yunwei]# grep "a\{2,4\}b" 1.txt#使用扩展正则时,需要使用egrep命令过滤[root@localhost yunwei]# egrep "a{2,4}b" 1.txt#匹配前一个字符至少出现一次以上[root@localhost yunwei]# egrep "a+" 1.txt#基本正则实现方式,匹配前一个字符至少出现一次以上[root@localhost yunwei]# grep "a\{1,\}" 1.txt#匹配前一个字符出现了0次或一次[root@localhost yunwei]# egrep "a?b" 1.txt#基本正则实现方式,匹配前一个字符出现了0次或一次[root@localhost yunwei]# grep "a\{0,1\}b" 1.txt#或者[root@localhost yunwei]# egrep "ab|acb|aaab" 1.txt#组合为整体[root@localhost yunwei]# egrep "(ab)" 1.txtabaabaaaabaaaaaaabaaaaaaaaaaaaab[root@localhost yunwei]# egrep "(acb)" 1.txtacb[root@localhost yunwei]# egrep "(aaab)" 1.txt#单词边界[root@localhost yunwei]# grep "the" 1.txtaabb the ccddabcthethexxooxxootheooxx[root@localhost yunwei]# egrep "\bthe\b" 1.txtaabb the ccdd[root@localhost yunwei]# egrep "\bthe" 1.txtaabb the ccddthexxoo[root@localhost yunwei]# egrep "the\b" 1.txtaabb the ccddabcthe
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文件中
#打印文件第一行内容[root@localhost yunwei]# sed -n '1p' /etc/passwdroot:x:0:0:root:/root:/bin/bash#打印文件第三行内容[root@localhost yunwei]# sed -n '3p' /etc/passwddaemon:x:2:2:daemon:/sbin:/sbin/nologin#打印文件第3行到6行[root@localhost yunwei]# sed -n '3,6p' /etc/passwddaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/sync#打印文件第3行到6行[root@localhost yunwei]# head -6 /etc/passwd | tail -4daemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/sync#利用正则表达式匹配以root开头的行(正则表达式要放在//内)[root@localhost yunwei]# sed -n '/^root/p' /etc/passwd#匹配以bash结尾的行[root@localhost yunwei]# sed -n '/bash$/p' /etc/passwd[root@localhost yunwei]# sed -n '/nologin$/p' /etc/passwd#打印文件最后一行,打印行号[root@localhost yunwei]# sed -n '$=' /etc/passwd70[root@localhost yunwei]# sed -n '/^root/=' /etc/passwd1#拷贝文件练习[root@localhost opt]# cp /etc/passwd /opt/test#删除文件2到4行[root@localhost opt]# sed '2,4d' test | wc -l67#使用i选项直接修改源文件[root@localhost opt]# sed -i '2,4d' test#使用分号分隔[root@localhost opt]# sed -i '10d;12d' test[root@localhost opt]# sed -n '$=' test62#制作素材[root@localhost opt]# vim 1.txtaaaabbbbbbbbbbaaaacccccaaaaadddddaaaa[root@localhost opt]# sed -n '/aaaa/p' 1.txtaaaabbbbbbbbbbaaaacccccaaaaadddddaaaa#取反删除[root@localhost opt]# sed -i '/cccc/!d' 1.txt[root@localhost opt]# cat 1.txtccccaaaa[root@localhost opt]# vim 1.txtaaaabbbbddddaaaazzzzaaaaccccaaaa#删除以ccc开头的行[root@localhost opt]# sed -i '/^cccc/d' 1.txt[root@localhost opt]# cat 1.txtaaaabbbbddddaaaazzzzaaaa#删除空行[root@localhost opt]# sed -i '/^$/d' 1.txt[root@localhost opt]# cat 1.txt#准备素材[root@localhost opt]# vim xx.txt2021 2020 2019 20182021 2021 2020 20192021 2022 2021 2020#替换文件每一行匹配到的第一个字串[root@localhost opt]# sed 's/2021/xxxx/' xx.txtxxxx 2020 2019 2018xxxx 2021 2020 2019xxxx 2022 2021 2020#替换文件每一行匹配到的第二个字串[root@localhost opt]# sed 's/2021/xxxx/2' xx.txt2021 2020 2019 20182021 xxxx 2020 20192021 2022 xxxx 2020#替换文件每一行匹配到的所有指定字串[root@localhost opt]# sed 's/2021/xxxx/g' xx.txtxxxx 2020 2019 2018xxxx xxxx 2020 2019xxxx 2022 xxxx 2020#将匹配到的第一个字串替换成空[root@localhost opt]# sed 's/2021//' xx.txt2020 2019 20182021 2020 20192022 2021 2020#将匹配到的第=二字串替换成空[root@localhost opt]# sed 's/2021//2' xx.txt2021 2020 2019 20182021 2020 20192021 2022 2020#替换时屏蔽默认输出[root@localhost opt]# sed -n 's/root/xxoo/g' test[root@localhost opt]# sed -n 's/root/xxoo/gp' testxxoo:x:0:0:xxoo:/xxoo:/bin/bashoperator:x:11:0:operator:/xxoo:/sbin/nologin#替换符可以使用任意的特殊符号[root@localhost opt]# sed 's#2021#xxoo#' xx.txtxxoo 2020 2019 2018xxoo 2021 2020 2019xxoo 2022 2021 2020[root@localhost opt]# sed 's,2021,xxoo,' xx.txtxxoo 2020 2019 2018xxoo 2021 2020 2019xxoo 2022 2021 2020[root@localhost opt]# sed 's!2021!xxoo!' xx.txtxxoo 2020 2019 2018xxoo 2021 2020 2019xxoo 2022 2021 2020[root@localhost opt]# sed 's;2021;xxoo;' xx.txtxxoo 2020 2019 2018xxoo 2021 2020 2019xxoo 2022 2021 2020[root@localhost opt]# sed 's*2021*xxoo*' xx.txtxxoo 2020 2019 2018xxoo 2021 2020 2019xxoo 2022 2021 2020[root@localhost opt]# sed 's:2021:xxoo:' xx.txtxxoo 2020 2019 2018xxoo 2021 2020 2019xxoo 2022 2021 2020#将文件中/bin/bash替换成/bin/sh[root@localhost opt]# sed -n 's/\/bin\/bash/\/bin\/sh/gp' test[root@localhost opt]# sed -n 's,/bin/bash,/bin/sh,gp' test#使用sed给文件1-7行批量添加注释[root@localhost opt]# sed -n '1,7s/^/#/p' test#使用sed给文件1-7行批量添加注释,直接修改源文件[root@localhost opt]# sed -i '1,7s/^/#/p' test#批量去除1-7行的注释[root@localhost opt]# sed -n '1,7s/^#//p' test#批量去除1-7行的注释,直接修改源文件[root@localhost opt]# sed -i '1,7s/^#//p' test#将文件中所有的数字替换成空[root@localhost opt]# sed -n 's/[0-9]//gp' test#将文件中所有的英文字母替换成空[root@localhost opt]# sed -n 's/[a-Z]//gp' test#准备素材[root@localhost opt]# vim a.txtxxxxxxxyyyyyyyzzzzzz#将a.txt文件内容导入到test文件中,默认读一行导一遍[root@localhost opt]# sed 'r/opt/a.txt' test#指定导入的行,导入到test文件第一行下边[root@localhost opt]# sed '1r/opt/a.txt' testroot:x:0:0:root:/root:/bin/bashxxxxxxxyyyyyyyzzzzzz#指定连续导入的行[root@localhost opt]# sed '1,3r/opt/a.txt' testroot:x:0:0:root:/root:/bin/bashxxxxxxxyyyyyyyzzzzzzroot:x:0:0:root:/root:/bin/bashxxxxxxxyyyyyyyzzzzzzroot:x:0:0:root:/root:/bin/bashxxxxxxxyyyyyyyzzzzzz#将a.txt文件第一行内容导出到b.txt文件中[root@localhost opt]# sed '1w b.txt' a.txt[root@localhost opt]# cat b.txtxxxxxxx
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示例:
#准备素材[root@localhost opt]# vim test.txthello the womanwelcome to china#打印文件的第一列[root@localhost opt]# awk '{print $1}' test.txthellowelcome#打印文件第一列和第三列[root@localhost opt]# awk '{print $1,$3}' test.txthello womanwelcome china#打印passwd文件第一列(默认没有空格与tab键作为分隔符,打印文件所有内容)[root@localhost opt]# awk '{print $1}' /etc/passwd#手动指定以:作为分隔,打印文件第一列[root@localhost opt]# awk -F: '{print $1}' /etc/passwd#打印文件第一列与第七列[root@localhost opt]# awk -F: '{print $1,$7}' /etc/passwd#通过[]集合匹配多种单个字符作为分隔符,打印用户名与解释器字段[root@localhost opt]# awk -F[:/] '{print $1,$10}' /etc/passwd#通过正则表达式过滤以root开头的行[root@localhost opt]# awk -F: '/^root/{print}' /etc/passwdroot:x:0:0:root:/root:/bin/bash#通过正则表达式过滤以root开头的行,打印第1列与第7列[root@localhost opt]# awk -F: '/^root/ {print $1,$7}' /etc/passwdroot /bin/bash#打印文件每一行与每一行的列数[root@localhost opt]# awk -F: '{print NR,NF}' /etc/passwd#打印文件每一行与每一行的列数,并打印最后一列[root@localhost opt]# awk -F: '{print NR,NF,$NF}' /etc/passwd#通过常量打印执行的列[root@localhost opt]# awk -F: '{print $1,"用户的解释器为:",$7}' /etc/passwdroot 用户的解释器为: /bin/bash#匹配第一列包含root的行[root@localhost opt]# awk -F: '$1~/root/' /etc/passwdroot:x:0:0:root:/root:/bin/bash#排除第7列noloogin的行,打印第1列与第7列[root@localhost opt]# awk -F: '$7!~/nologin/{print $1,$7}' /etc/passwd#利用扩展正则过滤,以root或者adm开头的行,打印第1列与第7列[root@localhost opt]# awk -F: '/^(root|adm)/{print $1,$7}' /etc/passwdroot /bin/bashadm /sbin/nologin
awk使用数值/字符串比较设置条件
- 等于: ==
- 不等于: !=
- 大于: >
- 大于等于: >=
- 小于: <
- 小于等于:<=
#打印行号等于3[root@localhost opt]# awk 'NR==3{print}' /etc/passwddaemon:x:2:2:daemon:/sbin:/sbin/nologin#使用sed更加方便打印某一行[root@localhost opt]# sed -n '3p' /etc/passwddaemon:x:2:2:daemon:/sbin:/sbin/nologin#打印文件中第3列大于等于1000,打印第1列,第3列,第7列[root@localhost opt]# awk -F: '$3>=1000{print $1,$3,$7}' /etc/passwdlisi 1000 /bin/bash#打印文件中第三列小于1000,打印第1列,第3列,第7列[root@localhost opt]# awk -F: '$3<1000{print $1,$3,$7}' /etc/passwdroot 0 /bin/bash#打印文件中第3列大于500并且小于1000,打印第1列,第3列,第7列[root@localhost opt]# awk -F: '$3>500 && $3<1000 {print $1,$3,$7}' /etc/passwdpolkitd 999 /sbin/nologin#打印第一列不等于root的行[root@localhost opt]# awk -F: '$1!="root"{print}' /etc/passwd
awk过滤时机:awk ‘BEGIN{指令} {指令} END{指令}’ 文件名
- BEGIN{指令} #读取文件内容之前执行指令,指令执行一次,行前处理
- {指令} #读取文件过程中执行,指令逐行执行,读一行,执行一次
- END{指令} #读取文件内容结束后执行指令,指令执行一次,行后处理
#BEGIN{指令}行前处理[root@localhost opt]# awk 'BEGIN{print "正在处理中"}'正在处理中#定义变量[root@localhost opt]# awk "BEGIN{x=10;print x}"10#四则运算[root@localhost opt]# awk "BEGIN{x=10;print x+5}"15[root@localhost opt]# awk "BEGIN{x=10;print x+5}"15[root@localhost opt]# awk "BEGIN{x=10;print x-5}"5[root@localhost opt]# awk "BEGIN{x=10;print x*5}"50[root@localhost opt]# awk "BEGIN{x=10;print x/5}"2[root@localhost opt]# awk "BEGIN{print 10+10}"20[root@localhost opt]# awk "BEGIN{print 10-5}"5[root@localhost opt]# awk "BEGIN{print 10*2}"20[root@localhost opt]# awk "BEGIN{print 10/3}"3.33333[root@localhost opt]# awk "BEGIN{print 10%3}"1#通过awk统计系统里使用bash解释器的用户有什么个?[root@localhost opt]# awk 'BEGIN{x=0}/bash$/{x++}END{print x}' /etc/passwd27[root@localhost opt]# awk '/bash$/{x++}END{print x}' /etc/passwd27
awk分支结构
- if单分支格式:if(条件){指令}
- if双分支格式:if(条件){指令}else{指令}
#if单分支统计passwd文件中UID大于或等于1000的用户个数awk -F: '{if($3>=1000){x++}} END{print x}' /etc/passwdif($3>=1000){x++}[root@localhost ~]# awk -F: '{if($3>=1000){x++}}END{print x}' /etc/passwd#if双分支统计passwd文件中UID大于等于1000的用户,和小于1000的用户个数[root@localhost ~]# awk -F: '{if($3>=1000){i++} else{x++}} END{print i,x}' /etc/passwd
awk数组
- 定义数组格式1:数组名[下标]=值
- 定义数组格式2:数组名[下标]
- 数组的用法:for(变量名 in 数组名) {print 数组名[变量]}
#awk定义数组方式[root@localhost ~]# awk 'BEGIN{x[0]=10;x[1]=20;print x[0],x[1]}'10 20#awk定义数组方式[root@localhost ~]# awk 'BEGIN{x[0]++;print x[0]}'1
awk循环结构
- 命令格式:for(变量名 in 数组名){print 数组名[变量]}
[root@localhost ~]# awk 'BEGIN{a[0]=00;a[1]=11;a[2]=22;for(i in a){print i,a[i]}}'0 01 112 22
- awk命令格式2:前置命令 | awk [选项] ‘条件{指令}’
#通过awk打印剩余内存[root@localhost opt]# free -h | grep Mem | awk '{print $4}'134M[root@localhost opt]# free -h | awk '/Mem/{print $4}'134M#用awk写一个监控脚本,监控网卡的进出口流量[root@localhost ~]# vim while_liuliang.sh#!/bin/bashwhile :doclearifconfig ens32 | awk '/inet /{print "IP:",$2}'ifconfig ens32 | awk '/RX p/{print "入口流量:",$5}'ifconfig ens32 | awk '/TX p/{print "出口流量:",$5}'sleep 0.1done#使用awk过滤系统根分区使用情况[root@localhost ~]# df -h | grep '/$' | awk '{print $4}' | awk -FG '{print $1}'51#过滤根分区剩余空间与物理内存空间[root@localhost ~]# vim df_free.sh#!/bin/bashdf -h | grep '/$' | awk '{print "根分区剩余空间:",$4}'free -h | grep Mem | awk '{print "物理内存剩余空间:", $4}'#通过awk统计用户登录系统的次数[root@localhost ~]# who | awk '{ip[$1]++}END{for(i in ip)print i,ip[i]}'root 1
cron周期性计划任务
- cron周期性计划任务用来定期执行程序,目前最主要的用途是定期备份数据
- 软件包名:cronie、crontabs
- 服务名:crond
- 日志文件:/var/log/cron
cron定义时间格式
* 执行的命令
分 时 日 月 周
分钟:从0到59之间的整数
小时:从0到23之间的整数
日期:从1到31之间的整数
月份:从1到12之间的整数
星期:0~6之间的整数,0代表周日
* #每分,每时,每天,每月,每周
, #分隔多个不连续的时间
- #指定连续时间范围
/ #指定执行任务的时间间隔
#软件包默认系统自动安装[root@localhost ~]# rpm -q croniecronie-1.4.11-19.el7.x86_64#服务默认随机自启[root@localhost ~]# systemctl status crond#cron定义时间格式* * * * * 执行的命令分 时 日 月 周分钟:从0到59之间的整数小时:从0到23之间的整数日期:从1到31之间的整数月份:从1到12之间的整数星期:0~6之间的整数,0代表周日* #每分,每时,每天,每月,每周, #分隔多个不连续的时间- #指定连续时间范围/ #指定执行任务的时间间隔#每周5在上8点执行一个任务00 8 * * 5 xx命令#每天晚上23:30执行一个任务30 23 * * * xx命令#日期跟星期不能同时定义,发生矛盾(没有这么定义的!)30 23 1 * 2 xx命令#每月1号23:30分执行一个任务30 23 1 * * xx命令#每月1、3、5号23:30执行一个任务30 23 1,3,5 * * xx命令#每周1、3、5凌晨3点执行一个任务00 3 * * 1,3,5 xx命令#每月2-5号凌晨3:30分执行一个任务30 3 2-5 * * xx命令#每两小时执行一个任务* */2 * * * xx命令#每两分钟执行一个任务*/2 * * * * xx命令
- crontab:用于管理计划任务
- crontab -e -u 用户名 #编写计划任务
- crontab -l -u 用户名 #查看计划任务
- crontab -r -u 用户名 #清楚计划任务
#每一分钟执行一个任务[root@localhost ~]# crontab -e*/1 * * * * date >> /opt/date.txt[root@localhost ~]# cat /opt/date.txt2021年 05月 23日 星期日 17:30:02 CST#每周6凌晨3:30分备份/var/log/日志文件[root@localhost ~]# crontab -e30 3 * * 6 tar -czf `date +%F`-log.tar.gz /var/log/*.log#查看计划任务[root@localhost ~]# crontab -l30 3 * * 6 tar -czf `date +%F`-log.tar.gz /var/log/*.log#清除计划任务[root@localhost ~]# crontab -r[root@localhost ~]# crontab -lno crontab for root
SELinux系统内核安全机制
- Security-Enhanced Linux 美国NSA国家安全局主导开发,一套增强Linux系统安全的强制访问控制体系
- 集成到Linux内核(2.6及以上)针对用户、进程、目录和文件提供了预设的保护策略,以及管理工具
- SELinux运行模式
- enforcing #强制模式
- permissive #宽松模式
- disabled #禁用模式
- SELinux运行模式切换
- 查看当前运行模式:getenforce
- 临时切换运行模式:setenforce 1|0 #1强制模式,0宽松模式
#查看当前运行模式[root@localhost ~]# getenforceEnforcing #默认为强制模式#切换运行模式为宽松模式[root@localhost ~]# setenforce 0[root@localhost ~]# getenforcePermissive#切换运行模式为强制模式[root@localhost ~]# setenforce 1[root@localhost ~]# getenforceEnforcing
- SELinux配置文件:/etc/selinux/config
#永久修改运行模式[root@localhost ~]# vim /etc/selinux/config...SELINUX=disabled
环境准备
#安装httpd与vsftpd服务[root@localhost ~]# rpm -q httpdhttpd-2.4.6-88.el7.centos.x86_64[root@localhost ~]# rpm -q vsftpdvsftpd-3.0.2-25.el7.x86_64#启动服务[root@localhost ~]# systemctl start httpd[root@localhost ~]# systemctl start vsftpd#查看运行状态[root@localhost ~]# systemctl status httpd[root@localhost ~]# systemctl status vsftpd#关闭防火墙[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:丢弃任何来访的数据包
#开启防火墙[root@localhost ~]# systemctl start firewalld#查看默认区域[root@localhost ~]# firewall-cmd --get-default-zonepublic#修改默认区域firewall-cmd --set-default-zone=区域名#将默认区域修改为block[root@localhost ~]# firewall-cmd --set-default-zone=blocksuccess[root@localhost ~]# firewall-cmd --get-default-zoneblock#将默认区域修改为dorp[root@localhost ~]# firewall-cmd --set-default-zone=dropsuccess[root@localhost ~]# firewall-cmd --get-default-zonedrop#将默认区域修改为public[root@localhost ~]# firewall-cmd --set-default-zone=publicsuccess[root@localhost ~]# firewall-cmd --get-default-zonepublic#查看区域规则firewall-cmd --zone=区域名 --list-all#查看public所有规则[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: default #默认区域icmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client #允许访问的服务ports:protocols:masquerade: noforward-ports:source-ports:icmp-blocks:rich rules:#为public区域添加http协议,使用 --add-service=服务名[root@localhost ~]# firewall-cmd --zone=public --add-service=httpsuccess[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: defaulticmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client http #添加http协议ports:protocols:masquerade: noforward-ports:source-ports:icmp-blocks:rich rules:#为public添加ftp协议[root@localhost ~]# firewall-cmd --zone=public --add-service=ftpsuccess[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: defaulticmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client http ftp #添加ftp协议ports:protocols:masquerade: noforward-ports:source-ports:icmp-blocks:rich rules:
封网段开服务
#若针对永久配置需添加 --permanent#使用 -- add-source=网段地址#为public区域永久添加http协议[root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=httpsuccess[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: defaulticmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client http ftpports:protocols:masquerade: noforward-ports:source-ports:icmp-blocks:rich rules:#为public区域永久添加ftp协议[root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=ftpsuccess[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: defaulticmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client http ftpports:protocols:masquerade: noforward-ports:source-ports:icmp-blocks:rich rules:#永久修改需重新加载防火墙配置firewall-cmd --reload[root@localhost ~]# firewall-cmd --reloadsuccess#单独拒绝某一个IP[root@localhost ~]# firewall-cmd --zone=block --add-source=192.168.0.24success[root@localhost ~]# firewall-cmd --zone=block --list-allblock (active)target: %%REJECT%%icmp-block-inversion: nointerfaces:sources: 192.168.0.24services:ports:protocols:masquerade: noforward-ports:source-ports:icmp-blocks:rich rules:#删除规则:--remove-source#删除block区域的指定IP[root@localhost ~]# firewall-cmd --zone=block --remove-source=192.168.0.24success[root@localhost ~]# firewall-cmd --zone=block --list-allblock#删除public区域的ftp协议[root@localhost ~]# firewall-cmd --zone=public --remove-service=ftpsuccess[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: defaulticmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client http
- 防火墙端口映射
- 本地应用的端口重定向(端口1 > 端口2)从客户机访问 端口1 的请求,自动映射到本机端口2
#当有人访问5432端口时,映射到本机的80端口[root@localhost ~]# firewall-cmd --zone=public --add-forward-port=port=5432:proto=tcp:toport=80success#命令解释:--add--forward #添加转发端口port=port=5432 #指定转发的端口proto=tcp #指定tcp协议toport=80 #指定目标端口[root@localhost ~]# firewall-cmd --zone=public --list-allpublic (active)target: defaulticmp-block-inversion: nointerfaces: ens32sources:services: ssh dhcpv6-client httpports:protocols:masquerade: noforward-ports: port=5432:proto=tcp:toport=80:toaddr=source-ports:icmp-blocks: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链:出站规则,限制防火墙主机上层应用产生的数据包是否可以出站需要的链
目标操作
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 类型
- 创建规则注意事项
- 可以不指定表,默认为filter表
- 如果没有找到匹配条件,执行防火墙默认规则
- 选项/链名/目标操作用大写字母,其余都小写
主机型防火墙规则配置
#安装iptables服务[root@master ~]# yum -y install iptables-services[root@master ~]# systemctl start iptables#拒绝icmp访问[root@master ~]# iptables -t filter -I INPUT -p icmp -j REJECT#查看规则[root@master ~]# iptables -L -n --line-numbers#测试icmp访问[root@slave ~]# ping 192.168.0.10PING 192.168.0.10 (192.168.0.10) 56(84) bytes of data.From 192.168.0.10 icmp_seq=1 Destination Port Unreachable[root@master ~]# iptables -t filter -I INPUT -p icmp -j DROP[root@master ~]# iptables -t filter -I INPUT -p icmp -j ACCEPT#清空某一条规则(默认为filter表)[root@iptables ~]# iptables -t filter -D INPUT 8#清空所有规则(默认为filter表所有规则)[root@master ~]# iptables -F#清空其他表所有规则[root@master ~]# iptables -t nat -F[root@master ~]# iptables -t raw -F[root@master ~]# iptables -t mangle -F#为filter表INPUT链添加规则,允许任何人使用TCP协议访问本机[root@master ~]# iptables -t filter -I INPUT -p tcp -j ACCEPT#为filter表INPUT链添加规则至第一行,允许任何人使用UDP协议访问本机[root@master ~]# iptables -t filter -I INPUT -p udp -j ACCEPT#为filter表INPUT链添加规则至第二行,允许任何人使用ICMP协议访问本机[root@master ~]# iptables -t filter -I INPUT 2 -p icmp -j ACCEPT[root@master ~]# iptables -nLChain INPUT (policy ACCEPT)target prot opt source destinationACCEPT udp -- 0.0.0.0/0 0.0.0.0/0ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0#查看INPUT链规则[root@master ~]# iptables -nL INPUTChain INPUT (policy ACCEPT)target prot opt source destinationACCEPT udp -- 0.0.0.0/0 0.0.0.0/0ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0#清空filter表所有规则[root@master ~]# iptables -F
设置防火墙默认规则
#查看filter表[root@master ~]# iptables -t filter -nLChain INPUT (policy ACCEPT) //默认规则target prot opt source destinationChain FORWARD (policy ACCEPT) //默认规则target prot opt source destinationChain OUTPUT (policy ACCEPT) //默认规则target prot opt source destination#允许22号端口被访问[root@master ~]# iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT[root@master ~]# iptables -nLChain INPUT (policy ACCEPT)target prot opt source destinationACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22#将filter表INPUT链默认规则修改为DROP[root@master ~]# iptables -t filter -P INPUT DROP[root@master ~]# iptables -nLChain INPUT (policy DROP) #默认为拒绝target prot opt source destinationACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 #只允许22端口访问,其他全部拒绝
#将默认规则修改为ACCEPT[root@master ~]# iptables -t filter -P INPUT ACCEPT#清空防火墙规则[root@master ~]# iptables -F#设置防火墙拒绝所有80端口的访问[root@master ~]# iptables -t filter -I INPUT -p tcp --dport 80 -j REJECT#查看规则[root@master ~]# iptables -nL#安装httpd服务[root@master ~]# yum -y install httpd#启动服务[root@master ~]# systemctl start httpd#修改默认首页[root@master ~]# echo xxoo > /var/www/index.html#访问测试[root@slave ~]# curl http://192.168.0.10[root@master ~]# iptables -F#单独拒绝某个IP[root@master ~]# iptables -t filter -I INPUT -s 192.168.0.20 -j REJECT#查看规则[root@master ~]# iptables -nLChain INPUT (policy ACCEPT)target prot opt source destinationREJECT all -- 192.168.0.20 0.0.0.0/0 reject-with icmp-port-unreachable192.168.0.20访问测试[root@slave ~]# curl http://192.168.0.10curl: (7) Failed connect to 192.168.0.10:80; 拒绝连接#拒绝客户端访问本机网卡的80端口[root@master ~]# iptables -t filter -I INPUT -i ens32 -p tcp --dport 80 -j REJECT#客户端测试[root@agent ~]# curl http://192.168.0.10curl: (7) Failed connect to 192.168.0.10:80; 拒绝连接[root@master ~]# iptables -F#设置防火墙拒绝某个网段[root@master ~]# iptables -t filter -I INPUT -s 192.168.1.0/24 -j REJECT#查看规则[root@master ~]# iptables -nLChain INPUT (policy ACCEPT)target prot opt source destinationREJECT 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
#开启路由转发功能[root@proxy ~]# echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf[root@proxy ~]# sysctl -p //加载配置立即生效net.ipv4.ip_forward = 1#查看路由转发[root@proxy ~]# cat /proc/sys/net/ipv4/ip_forward1
- 第二台服务器提供网站服务:web27将网关指向1192.168.0.26
#安装httpd服务[root@web1 ~]# yum -y install httpd#修改默认首页[root@web1 ~]# echo web27 > /var/www/html/index.html[root@web1 ~]# systemctl start httpd[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端口
[root@proxy ~]# iptables -I FORWARD -s 192.168.1.30 -p tcp --dport 80 -j DROP#客户端192.168.1.30访问测试:curl http://192.168.0.20#拒绝所有客户端地址访问内网80端口[root@iptables ~]# iptables -t filter -I FORWARD -p tcp --dport 80 -j REJECT[root@proxy ~]# iptables -F
防火墙扩展
- 命令格式:iptables 选项 链名 -m 扩展模块 —具体扩展条件 -j 动作
#根据MAC地址封锁主机,安装nmap扫描获取地方IP的MAC地址[root@proxy ~]# yum -y install nmap#扫描对方主机IP[root@proxy ~]# nmap -s 192.168.1.28Starting Nmap 6.40 ( http://nmap.org ) at 2020-09-25 17:12 CSTNmap scan report for 192.168.0.111Host is up (0.00044s latency). //当前主机状态MAC Address: 00:0C:29:CA:87:81 (VMware) //MAC地址Nmap done: 1 IP address (1 host up) scanned in 4.05 seconds#通过MAC地址限制对方访问[root@proxy ~]# iptables -t filter -I FORWARD -p tcp --dport 80 -m mac --mac-source 00:0C:29:D5:29:0F -j REJECT
基于多端口设置过滤规则
[root@proxy ~]# iptables -t filter -I FORWARD -p tcp -m multiport --dports 20,21,80,443 -j ACCEPT#multiport :多端口模块#根据IP范围设置封锁规则[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#iprange模块:ip范围模块#--src-range:源IP#--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 |
#实现192.168.1.28转换为192.168.0.26[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#POSTROUTING:路由后链#-s:指定源地址为192.168.1.0网段的地址#-p:想要通过tcp协议#--dport:访问目标的80端口时#-j:SNAT转换#--to-source:转换源地址为192.168.0.26#web1动态查看访问日志[root@web1 ~]# tail -f /var/log/httpd/access_logclient 192.168.1.30访问网站curl http://192.168.0.27#所有iptables规则都是临时规则,如果需要永久保留规则需要执行如下命令[root@proxy ~]# service iptables save
sudo用户提权
- 管理员提前为用户设置执行权限许可
- 被授权用户有权执行授权命令
- 配置文件:/etc/sudoers
- 命令格式:sudo 特权命令
#修改/etc/sudoers文件,为lisi用户授予相关脚本的执行权限,允许通过systemctl工具来管理系统服务,修改/etc/sudoers配置文件可以用vim编辑文件,或者使用visudo命令修改[root@master ~]# visudo.. ..root ALL=(ALL) ALLlisi ALL=(root) /bin/systemctl解释:授权lisi用户以root身份执行systemctl命令#切换lisi用户验证sudo权限[root@master ~]# su - lisi[lisi@master ~]$ sudo -l.. ..用户 lisi 可以在 master 上运行以下命令:(root) /bin/systemctl#通过sudo启动服务[lisi@master ~]$ sudo systemctl start httpd[lisi@master ~]$ sudo systemctl status httpd[lisi@master ~]$ sudo systemctl stop httpd#为lisi用户添加sudo权限,允许lisi用户可以创键用户,修改用户密码[root@master ~]# visudo.. ..lisi ALL=(root) /bin/systemctl,/sbin/useradd,/bin/passwd,!/bin/passwd root // ! 取反#切换lisi用户验证sudo权限[lisi@master ~]$ sudo useradd haha[lisi@master ~]$ id hahauid=1001(haha) gid=1001(haha) 组=1001(haha)#修改haha用户密码[lisi@master ~]$ sudo passwd haha更改用户 haha 的密码 。新的 密码:123无效的密码: 密码少于 8 个字符重新输入新的 密码:123passwd:所有的身份验证令牌已经成功更新。#为sudo机制启用日志记录,以便跟踪sudo执行操作[root@master ~]# visudo.. ..Defaults logfile="/var/log/sudo.log" #手动添加.. ..#普通用户执行sudo命令[lisi@master ~]$ sudo systemctl start httpd#查看日志是否记录[root@master ~]# cat /var/log/sudo.logSep 24 12:57:09 : lisi : TTY=pts/1 ; PWD=/home/lisi ; USER=root ;COMMAND=/bin/systemctl start httpd
OpenSSH
- OpenSSH开源免费提供ssh远程安全登录的程序
- ssh协议端口:22/tcp
- 服务名:sshd
- ssh提供密钥认证登录方式
#生成公私钥[root@localhost ~]# ssh-keygenGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):Created directory '/root/.ssh'.Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:SHA256:Yjcq3+SAOmVQgCbRVC+6QgJp+rss5MK+anEwitmi4Xo root@localhostThe key's randomart image is:+---[RSA 2048]----+|.=oo. ||oo. .. ||=. .. . ||+o.. . ||=++. o S ||O+.ooo + . ||Bo=oo o . ||+BEo o = ||O=*o . o |+----[SHA256]-----+#查看密钥文件[root@localhost ~]# ls .sshid_rsa id_rsa.pub#将公钥拷贝至其他主机[root@localhost ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.0.27#其他主机查看公钥文件[root@host-27 ~]# ls .sshauthorized_keys#验证是否实现密钥认证登录[root@localhost ~]# ssh 192.168.0.27Last login: Sat Jun 5 00:41:47 2021 from 192.168.0.1[root@host-27 ~]#[root@host-27 ~]# exit登出
scp远程复制工具
- scp可以实现主机之间的文件拷贝
#将本地文件拷贝至远程主机[root@localhost ~]# touch /opt/test.txt[root@localhost ~]# scp /opt/test.txt root@192.168.0.27:/opt#将远程主机文件拉取到本地[root@localhost ~]# scp root@192.168.0.27:/etc/fstab /opt[root@localhost ~]# ls /optfstab test.txt
提高ssh服务安全性
- 配置文件:/etc/ssh/sshd_config
https://blog.csdn.net/qq_28513801/article/details/90696863[root@master ~]# vim /etc/ssh/sshd_config.. ..#Port 22 #ssh默认监听端口#PermitRootLogin yes #是否允许root用户连接,yes允许,no不允许#PermitEmptyPasswords no #不允许空密码登录PasswordAuthentication yes #允许用密码登录AllowUsers 用户1 用户2 用户3@192.168.0.0/24 #定义账号白名单##DenyUsers 用户1 用户2 #定义账号黑名单
文件共享服务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匿名用户模式
#安装软件[root@ftp-server ~]# yum -y install vsftpd#启动服务[root@ftp-server ~]# systemctl start vsftpd#查看服务运行状态[root@ftp-server ~]# systemctl status vsftpd#客户端下载连接工具[root@client ~]# yum -y install ftp lftp#匿名用户权限介绍[root@localhost ftp]# vim /etc/vsftpd/vsftpd.conf...12 anonymous_enable=YES #是否允许匿名用户访问,yes允许,no不允许29 #anon_upload_enable=YES #是否允许匿名用户上传,yes允许,no不允许33 #anon_mkdir_write_enable=YES #是否允许匿名用户创建目录,yes允许,no不允许...anon_other_write_enable=yes #是否允许匿名用户写权限,yes允许,no不允许(手动添加)
vsftpd本地用户模式
#创建本地用户[root@localhost ~]# useradd ftpuser[root@localhost ~]# passwd ftpuser#修改主配置文件[root@localhost ~]# vim /etc/vsftpd/vsftpd.conf...12 anonymous_enable=NO #关闭匿名用户访问16 local_enable=YES #是否允许本地用户访问,yes允许,no不允许19 write_enable=YES #是否允许本地用户有写权限,yes允许,no不允许23 local_umask=022 #本地用户上传文件默认权限为75537 dirmessage_enable=YES #当用户第一次进入新目录时显示消息(了解)40 xferlog_enable=YES #启动xferlog日志记录,该文件记录传输数据53 #xferlog_file=/var/log/xferlog #日志文件位置,需删除注释43 connect_from_port_20=YES #启用数据传输端口49 #chown_username=whoever #改变上传文件的属主与属组60 #idle_session_timeout=600 #客户端连接超时时间63 #data_connection_timeout=120 #数据连接超时时间101 chroot_local_user=YES #是否允许本地用户切换目录,yes不允许,no允许115 listen=NO #是否开启监听IPV4的连接,默认没开启,改为yes126 pam_service_name=vsftpd #启用pam认证的文件名称,路径为/etc/pam.d/vsftpd127 userlist_enable=YES #是否启用控制名单文件,yes启用,no不启用,文件为/etc/vsftpd/user_list,如果启用控制名单功能,需要指定该文件为黑名单|白名单128 userlist_deny=no #yes拒绝user_list文件中用户登录ftp服务器(黑名单),no允许登录(白名单)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服务端配置
#安装nfs服务端软件包[root@localhost ~]# yum -y install nfs-utils#启动nfs服务[root@localhost ~]# systemctl start nfs[root@localhost ~]# systemctl enable nfs#查看服务端口信息[root@localhost ~]# ss -anptul | grep 2049udp UNCONN 0 0 *:2049 *:*udp UNCONN 0 0 :::2049 :::*tcp LISTEN 0 64 *:2049 *:*tcp LISTEN 0 64 :::2049 :::*#查看RPC服务端口信息[root@localhost ~]# ss -anptul | grep rpcbindudp UNCONN 0 0 *:111tcp LISTEN 0 128 *:111#创建共享目录[root@localhost ~]# mkdir /upload#修改nfs主配置文件:/etc/exports[root@localhost ~]# vim /etc/exports/upload 192.168.0.27(rw) 192.168.0.28(ro)/test 192.168.0.0/24(rw) #共享给指定网段共享文件夹路径 客户机地址(权限) 客户机地址(权限)#重启nfs服务[root@localhost ~]# systemctl restart nfs
客户端访问NFS
#列出有哪些NFS共享资源:showmount -e 服务器地址,如果客户端没有该命令需安装nfs-utils[root@client ~]# showmount -e 192.168.0.26Export list for 192.168.0.26:/upload 192.168.0.28,192.168.0.27#手动挂载NFS共享:mount[root@client ~]# mkdir /opt/upload[root@client ~]# mount 192.168.0.26:/upload /opt/upload服务器地址:文件夹路径 挂载点[root@client ~]# df -h文件系统 容量 已用 可用 已用% 挂载点...192.168.0.26:/upload 17G 1.2G 16G 7% /opt/upload#客户端验证是否可以是否共享目录[root@client ~]# cd /opt/upload/[root@client upload]# touch xx.txttouch: 无法创建"xx.txt": 权限不够#解释:默认客户端是以nfs用户身份访问远端的nfs服务器,如果nfs服务端共享的目录属主为root用户,那客户端默认是没有写权限#服务端开放允许以root身份访问[root@localhost ~]# vim /etc/exports/upload 192.168.0.27(no_root_squash,rw) 192.168.0.28(ro)解释:no_root_squash 不挤压root用户身份(允许以root身份访问)[root@localhost ~]# systemctl restart nfs#客户端验证[root@client upload]# touch xx.txt[root@client upload]# lsxx.txt#为普通用户授权访问nfs共享目录(通过ACL实现,nfs通过用户UID辨别用户身份)[root@localhost ~]# setfacl -m u:lisi:rwx /upload#设置SBIT权限[root@localhost ~]# chmod o+t /upload/#客户端lisi用户验证授权[lisi@client upload]$ touch lisi.txt[lisi@client upload]$ lslisi.txt xx.txt[lisi@client upload]$ rm -rf xx.txtrm: 无法删除"xx.txt": 不允许的操作#客户端实现开机挂载配置:/etc/fstab[root@localhost]# vim /etc/fstab192.168.0.220:/xxx /mnt/xxx nfs defaults,_netdev 0 0服务器地址:文件夹路径 挂载点 文件系统 defaults,_netdev 0 0#解释:_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
#a安装httpd服务[root@localhost ~]# yum -y install httpd#启动httpd服务[root@localhost ~]# systemctl start httpd#查看服务运行状态[root@localhost ~]# systemctl status httpd#客户端访问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)
#修改主配置文件指定域名[root@localhost ~]# vim /etc/httpd/conf/httpd.conf...ServerName www.abcd.com:80 #指定域名#重启httpd服务[root@localhost ~]# systemctl restart httpd#实现本地主机名与IP地址解析[root@localhost ~]# vim /etc/hosts...192.168.0.26 www.abcd.com#修改配置文件指定网页根目录存放位置[root@localhost ~]# vim /etc/httpd/conf/httpd.conf...DocumentRoot "/var/www/myweb"#创建网页根目录[root@localhost ~]# mkdir /var/www/myweb#创建测试页面[root@localhost ~]# vim /var/www/myweb/index.htmlabcd#重启httpd服务[root@localhost ~]# systemctl restart httpd#访问测试:curl http://www.abcd.comabcd
httpd虚拟web主机
虚拟web主机的特点:由同一台主机提供多个web站点
虚拟web主机实现的三种方式:
- 基于域名的虚拟主机:www.xxoo.com www.xxxx.com www.oooo.com
- 基于端口的虚拟主机
- 基于IP地址的虚拟主机
虚拟主机配置路径:/etc/httpd/conf.d/*.conf
虚拟主机配置:
ServerName 此站点的DNS名称
DocumentRoot 此站点的网页根目录
… …
基于域名虚拟web主机
[root@localhost ~]# vim /etc/httpd/conf.d/web.conf<VirtualHost *:80>ServerName www.baidu.comDocumentRoot /var/www/baidu</VirtualHost><VirtualHost *:80>ServerName www.nmsl.comDocumentRoot /var/www/nmsl</VirtualHost><VirtualHost *:80>ServerName www.alg.comDocumentRoot /var/www/alg</VirtualHost># 创建网页根目录[root@localhost ~]# mkdir /var/www/xxoo[root@localhost ~]# mkdir /var/www/xxxx[root@localhost ~]# mkdir /var/www/oooo#创建默认首页[root@localhost ~]# vim /var/www/xxoo/index.htmlxxoo[root@localhost ~]# vim /var/www/xxxx/index.htmlxxxx[root@localhost ~]# vim /var/www/oooo/index.htmloooo#配置本地解析——客户端配置(谁访问谁配)[root@localhost ~]# vim /etc/hosts192.168.0.26 www.xxoo.com192.168.0.26 www.xxxx.com192.168.0.26 www.oooo.com#重启服务[root@localhost ~]# systemctl restart httpd#访问测试[root@localhost ~]# curl http://www.xxoo.comxxoo[root@localhost ~]# curl http://www.xxxx.comxxxx[root@localhost ~]# curl http://www.oooo.comoooo
Ansible自动化运维
Ansible是2013年推出的一款IT自动化DevOps软件,基于Python语言开发,2015年被RedHat收购
Ansible特点:
Ansible基于Paramiko实现SSH协议链接通讯,默认只要被管理节点开启SSH服务,Ansible就可以管理远程主机
使用Ansible不需要在客户端主机(被管理主机)安装Agent
Ansible模块化设计,并且模块丰富,支持自定义模块,自定义模块可用任何语言编写
Ansible基于PyYAML模块支持Playbook,可以通过Playbook完成可重复的复杂工作
支持Jinjia2模板
批量管理工具:
- 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
[root@ansible-server ~]# systemctl stop firewalld[root@ansible-server ~]# systemctl disable firewalld[root@ansible-server ~]# setenforce 0[root@ansible-server ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
管理节点修改/etc/hosts文件实现本地解析
[root@ansible-server ~]# vim /etc/hosts...192.168.0.26 web1192.168.0.27 web2192.168.0.28 web3
管理节点与被管理节点实现SSH密钥认证
[root@ansible-server ~]# ssh-keygen
传递公钥到被管理节点
[root@ansible-server ~]# for i in web1 web2 web3> do> ssh-copy-id $i> done
验证SSH免密登录
[root@ansible-server ~]# ssh web1[root@web1 ~]# exit[root@ansible-server ~]# ssh web2[root@web2 ~]# exit[root@ansible-server ~]# ssh web3[root@web3 ~]# exit
安装Ansible软件包
- 安装ansible软件包,由于ansible需要epel源,本实验配置了阿里的epel源和阿里的Base源(Base源用于安装ansible所需依赖),本地的CentOS7镜像源
[root@ansible-server ~]# yum -y install wget #下载wget工具[root@ansible-server ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里Base源[root@ansible-server ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo #下载阿里epel源
安装ansible软件包
[root@ansible-server ~]# yum -y install ansible
查看ansible版本信息
[root@ansible-server ~]# ansible --versionansible 2.9.17
定义Ansible主机清单
- ansible主配置文件:/etc/ansible/ansible.cfg
- ansible默认清单文件:/etc/ansible/hosts
- 编辑清单文件定义主机组
[root@ansible-server ~]# vim /etc/ansible/hosts[websrvs]192.168.0.26192.168.0.27192.168.0.28
列出指定组内主机列表
[root@ansible-server ~]# ansible websrvs --list-hosthosts (4):192.168.0.26192.168.0.27192.168.0.28
ansible-doc命令介绍:
[root@ansible-server ~]# ansible-doc -l
显示ping模块帮助信息
[root@ansible-server ~]# ansible-doc -s ping
使用ping模块测试websrvs组主机连通性
[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模块示例:
#chdir参数表示执行命令之前,会先进入到指定的目录中[root@ansible-server ~]# ansible websrvs -m command -a 'chdir=/root/ ls'#creates参数表示如果/etc/passwd文件存在于远程主机中,则不执行对应命令,如果不存在,才执行”touch”命令[root@ansible-server ~]# ansible websrvs -m command -a 'creates=/etc/passwd touch /opt/passwd'#演示:creates参数在文件不存在情况下才会执行“touch”命令[root@ansible-server ~]# ansible websrvs -m command -a 'creates=/opt/passwd touch /opt/passwd'#removes参数表示如果/opt/abc文件不存在,就不执行“mv”命令,如果文件存在则执行“mv”命令[root@ansible-server ~]# ansible websrvs -m command -a 'removes=/opt/abc mv /opt/abc /root/'#演示:removes参数如果/opt/passwd文件不存在,就不执行“mv”命令[root@ansible-server ~]# ansible websrvs -m command -a 'removes=/opt/passwd mv /opt/passwd /root/'[root@ansible-server ~]# ansible websrvs -m command -a 'hostname'[root@ansible-server ~]# ansible websrvs -m command -a 'ip a s ens32'[root@ansible-server ~]# ansible websrvs -a 'uname -r' #查看内核信息[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 模块示例:
#查看/etc/passwd文件,并通过管道符传递给“wc -l”统计文件行数[root@ansible-server ~]# ansible websrvs -m shell -a 'cat /etc/passwd | wc -l'#查看/etc/passwd文件,并通过“>”将文件内容重定向至/opt/passwd文件中[root@ansible-server ~]# ansible websrvs -m shell -a 'cat /etc/passwd > /opt/passwd'#通过chdir参数进入/opt/目录,执行“ls”[root@ansible-server ~]# ansible websrvs -m shell -a 'chdir=/opt/ ls'#通过chdir参数进入/opt目录,执行“cat”查看passwd文件内容[root@ansible-server ~]# ansible websrvs -m shell -a 'chdir=/opt/ cat passwd'#查看主机名[root@ansible-server ~]# ansible websrvs -m shell -a 'hostname'#查看内核信息[root@ansible-server ~]# ansible websrvs -m shell -a 'uname -r'#查看ens32网卡的IP地址信息[root@ansible-server ~]# ansible websrvs -m shell -a 'ip a s ens32 | grep inet'#查看内存使用信息[root@ansible-server ~]# ansible websrvs -m shell -a 'free -h'#查看分区使用信息[root@ansible-server ~]# ansible websrvs -m shell -a 'df -h'#关闭防火墙&&设置开机不自起[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 模块,用于管理远程主机的服务,如:启动或停止服务
- 常用参数:
查看服务状态
[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 模块,用于将文件复制到远程主机
- 常用参数:
将本地/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~ #备份后文件
拷贝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 &
DHCP概述及原理:
DHCP地址分配的四次会话
DISCOVERY -OFFER -REQUEST -ACK
服务端基本概念:
租期:允许客户机组用IP地址的时间期限,单位为秒
作用域:分配给客户机的IP地址所在网段
地址池:用来动态分配的IP地址范围
安装、配置dhcpd服务
- 软件包:dhcp
- 服务名:dhcpd
- ** 配置文件:/etc/dhcp/


日志功能
- 系统和程序的“记事本”
- 记录系统和程序运行中发生的各种事件
- 通过查看日志可以了解信息以及排除故障
-
内核级系统日志
日志由系统服务rsyslog服务统一记录和管理
- 日志消息采用文本格式记录
- 主要记录的信息:事件发生的时间、主机、进程、内容(类似于:时间、地点、人物、发生的事情)
- 系统日志:/var/log/messages
常见日志文件介绍
| 日志文件 | 用途 | | —- | —- | | /var/log/messages | 记录内核信息、各种服务的公共信息 | | /var/log/boot.log | 记录系统启动过程的各种信息 | | /var/log/cron | 记录计划任务(**crond)的相关信息 | | /var/log/maillog | 记录邮件收发的相关信息 | | /var/log/secure | 记录与访问限制相关的安全信息** |

