第十章:Shell脚本编程
Shell概述
-
Shell是一门编程语言,如:C C++ java php 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 word
echo hello word
#赋予执行权限
[root@localhost ~]# chmod u+x hello.sh
#执行脚本
[root@localhost ~]# /root/hello.sh
hello word
- 编写创建用户脚本
[root@localhost ~]# vim user.sh
#!/bin/bash
useradd abc
passwd abc
[root@localhost ~]# chmod u+x user.sh
#非交互
[root@localhost ~]# vim user.sh
#!/bin/bash
useradd yyyy
echo 1 | passwd --stdin yyyy
[root@localhost ~]# ./user.sh
更改用户 yyyy 的密码 。
passwd:所有的身份验证令牌已经成功更新。
- 编写批量查看系统信息脚本
#查看系统版本信息,查看系统内核信息,查看系统内存信息,查看系统网卡信息,查看当前主机名
[root@localhost ~]# vim info.sh
cat /etc/redhat-release
uname -r
free -h
ifconfig ens32
hostname
#赋予执行权限
[root@localhost ~]# chmod u+x info.sh
#执行脚本
[root@localhost ~]# ./info.sh
CentOS Linux release 7.6.1810 (Core)
3.10.0-957.el7.x86_64
total used free shared buff/cache available
Mem: 972M 480M 147M 16M 344M 260M
Swap: 2.0G 239M 1.8G
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 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 0
TX packets 20635 bytes 1385581 (1.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
localhost.localdomain
- 编写搭建本地软件仓库的脚本
#编写搭建本地yum仓库脚本【版1,丢人版】
[root@localhost ~]# 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/*
touch /etc/yum.repos.d/local.repo
echo "[local]" > /etc/yum.repos.d/local.repo
echo "name=local_centos" >> /etc/yum.repos.d/local.repo
echo "baseurl=file:///mnt/centos" >> /etc/yum.repos.d/local.repo
echo "enabled=1" >> /etc/yum.repos.d/local.repo
echo "gpgcheck=0" >> /etc/yum.repos.d/local.repo
#编写搭建本地yum仓库脚本【版2,标准版】
[root@localhost ~]# vim yum.sh
#!/bin/bash
rm -rf /etc/yum.repos.d/*
echo "[local]
name=local_centos
baseurl=file:///mnt/centos
enabled=1
gpgcheck=0" > /etc/yum.repos.d/local.repo
#编写搭建本地yum仓库脚本【升级版】
[root@localhost ~]# vim yum.sh
#!/bin/bash
echo "正在配置本地yum仓库..."
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos &> /dev/null
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
mount -a
rm -rf /etc/yum.repos.d/*
echo "[local]
name=local_centos
baseurl=file:///mnt/centos
enabled=1
gpgcheck=0" > /etc/yum.repos.d/local.repo
echo "本地yum仓库配置以完成..."
yum clean all &> /dev/null
yum repolist | tail -1
#执行脚本
[root@localhost ~]# ./yum.sh
正在配置本地yum仓库...
本地yum仓库配置以完成...
repolist: 4,021
#带进度条版本
#!/bin/bash
echo "====正在搭建本地软件仓库===="
b=''
for ((i=0;$i<=20;i++))
do
let jinshu=$i*5
printf "[%-20s]%d%%\r" $b $jinshu
sleep 0.1
b=#$b
done
echo
rm -rf /etc/yum.repos.d/*
echo "[local]
name=local-centos-7.6
baseurl=file:///mnt/centos
enabled=1
gpgcheck=0" > /etc/yum.repos.d/centos.repo
x=`yum repolist | tail -1 | awk '{print $2}'`
echo "软件包数量为:$x"
脚本的执行方式
- 方法一:赋予脚本执行权限后,可用绝对路径或者当前路径执行
- 方法二:调用解释器执行脚本文件
#绝对路径执行脚本
[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.sh
hello word
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
[root@localhost ~]# sh hello.sh
hello word
[root@localhost ~]# tcsh hello.sh
hello word
[root@localhost ~]# csh hello.sh
hello 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.txt
2021-05-09-abc.txt
#``取命令结果作为参数
[root@localhost ~]# tar -czf "`date "+%F %X"`_log.tar.gz" /var/log/*.log
变量
-
以固定的名称存放可能变化的值,提高脚本的灵活度来适应多变的环境
-
定义变量:变量名=变量值,如:date=$(date +%F)(等号两边不要有空格)
-
定义变量注意事项:
- 变量名由字母/数字/下划线组成,区分大小写,不能以数字开头,不要使用命令和特殊符号
-
若指定的变量名已经存在,相当于为此变量重新赋值
-
取消变量:unset 变量名
num=5
echo $num
5
echo $[num+5]
10
#通过变量定义用户名
[root@localhost ~]# vim user.sh
#!/bin/bash
user=wangxin
useradd $user
echo 1 | passwd --stdin $user
[root@localhost ~]# ./user.sh
更改用户 wangxin 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# vim user.sh
#!/bin/bash
user=jiumei
useradd $user
echo 1 | passwd --stdin $user
[root@localhost ~]# ./user.sh
更改用户 jiumei 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# vim user.sh
#!/bin/bash
user=panghu
useradd $user
echo "用户$user创建成功"
echo 1 | passwd --stdin $user &> /dev/null
echo "用户$user密码设置成功"
[root@localhost ~]# ./user.sh
用户panghu创建成功
用户panghu密码设置成功
read标准输入取值
-
read 读取用户在键盘上输入的内容,并把内容存放在变量里,可以降低脚本的使用难度
-
命令格式:read -p “提示信息” 变量名
通过read创建用户
#!/bin/bash
read -p '请输入用户名:' user
useradd $user
echo "用户$user创建成功"
read -p '请设置用户密码:' pass
echo $pass | passwd --stdin $user &> /dev/null
echo "用户$user密码设置成功"
通过read安装软件包
#!/bin/bash
#通过read标准输入取值,安装软件包
read -p 请输入你要安装的软件包名称: package
yum -y install $package &> /dev/null
echo 正在安装软件包,请耐心等待...
b=''
for ((i=0;$i<=20;i++))
do
let jinshu=$i*5
printf "[%-20s]%d%%\r" $b $jinshu
sleep 0.1
b=#$b
done
echo
echo 软件包$package已经成功安装
变量种类
-
环境变量:变量名一般都大写,用来设置用户/系统环境
-
位置变量:bash内置,存储执行脚本时提供的命令参数
-
预定义变量:bash内置,可直接调用的特殊值,不能直接修改
-
自定义变量:用户自定义
-
env 命令查看系统所有环境变量
-
set 命令查看系统所有变量,包括用户自定义变量
-
环境变量
[root@localhost etc]# env
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
SSH_CONNECTION=192.168.0.1 51791 192.168.0.100 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
DISPLAY=localhost:10.0
_=/usr/bin/env
OLDPWD=/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代表错误)
$$ #显示脚本进程号(PID)
[root@localhost ~]# vim test.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
echo $*
echo $#
echo $$
echo $?
#赋予执行权限,执行脚本
[root@localhost ~]# ./test.sh xx oo dd
./test.sh $0
xx $1
oo $2
dd $3
xx oo dd $*
3 $#
15594 $$
0 $?
#通过位置变量创建用户并设置密码
#!/bin/bash
useradd $1 &> /dev/null
echo "用户$1创建成功"
echo $2 | passwd --stdin $1 &> /dev/null
echo "用户$1的密码设置成功,密码为$2"
判断文件状态
- -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+3
expr 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做数值运算
# let unm=1+1
echo $num
#let简写表达式 #let完整表达式
let num++ let num=num+1
let num-- let num=num-1
let num+=5 let num=num+5
let num-=5 let num=num-5
let num*=2 let num=num*2
let num/=3 let num=num/3
let num%=3 let num=num%3
字符串判断
- -z #字符串的值为空为真
- -n #字符串的值非空为真(相当于 ! -z)
[ -z $num ]
echo $?
[ ! -z $num ]
echo $?
第十一章:Shell条件判断与循环
条件判断结构
当条件满足时执行什么操作,当条件不满足时执行什么操作
- && #逻辑与(并且)
- || #逻辑或(或者)
- ; #条件之间没有逻辑关系
A && B #当A命令执行成功后才会执行B,如果A执行失败则B不执行
#判断存在且是文件执行拷贝操作(并且关系)
yum -y install vsftpd && systemctl start vsftpd && systemctl enable vsftpd && systemctl status vsftpd
A || B #当A命令执行失败后才会执行B,如果A执行成功则B不执行
#前便命令执行失败,后边命令则执行
ll /opt/xx.txt || touch /opt/xx.txt
A ; B #执行A命令后执行B,两者没有逻辑关系
hostname ; uname -rs ; cat /etc/centos-release
if 条件判断结构
- if 单分支语句,只能判断对,不能判断错
#第一种语法结构
if [条件判断];then
条件成立时,执行的命令
fi
#第二种语法结构
if [条件判断]
then
条件成立时,执行的命令
fi
#if单分支示例
vim if1.sh
#!/bin/bash
if [ -f /etc/passwd ];then
echo "存在"
fi
#!/bin/bash
if [ $(rpm -q httpd &> /dev/null; echo $?) -eq 0 ];then
echo 存在
fi
if 双分支语句,既能判断对,也能判断错
if [条件判断];then
条件成立时,执行命令a
else
条件不成立时,执行命令b
fi
#if双分支示例
vim if2.sh
#!/bin/bash
if [ -f /etc/abc.txt ];then
echo '空值'
else
echo '非空'
fi
#!/bin/bash
if [ $(rpm -q httpd &> /dev/null;echo $?) -eq 0 ];then
echo 存在
else
echo 不存在
echo 正在安装软件包
if [ $(yum -y install httpd &> /dev/null;echo $?) -eq 0 ];then
echo 软件包已经安装成功
else
echo 安装失败,没有软件包
fi
fi
#编写参数字的脚本,让计算机产生一个0-9随机数
#$RANDOM环境变量,里边存放的是0-65535之间的随机数
echo $RANDOM
#使用$RANDOM的值对10取余
echo $[RANDOM%10]
#编写猜数字脚本
vim if3.sh
#!/bin/bash
read -p '请输入0-9之间的随机数:' num
num1=$[RANDOM%10]
if [ $num -eq $num1 ];then
echo "恭喜你才对了,奖励一个哇塞女孩!"
else
echo "猜错了,请继续努力,奖品是一个哇塞女孩!"
echo "正确的结果为$num1"
fi
if 多分支语句
if [条件判断1];then
条件1成立时,执行命令a
elif [条件判断2];then
条件2成立时,执行命令b
elif [条件判断3];then
条件3成立时,执行命令c
...省略更多条件
else
所有条件都不成立时,执行命令d
fi
#!/bin/bash
if [ $(rpm -q httpd &> /dev/null;echo $?) -eq 0 ];then
echo 存在
elif [ $(rpm -q vsftpd &> /dev/null;echo $?) -eq 0 ];then
echo vsftpd存在,httpd不存在
echo =====正在安装httpd软件=====
b=''
for ((i=0;$i<=20;i++))
do
let jinshu=$i*5
printf "[%-20s]%d%%\r" $b $jinshu
sleep 0.1
b=#$b
done
echo
if [ $(yum -y install httpd &> /dev/null;echo $?) -eq 0 ];then
echo 软件包httpd已经安装成功!
else
echo httpd安装失败
fi
else
if [ $(yum -y install httpd vsftpd &> /dev/null;echo $?) -eq 0 ];then
echo 软件包httpd、vsftpd已经安装成功!
else
echo httpd安装失败
fi
fi
#编写判断成绩脚本
vim if5.sh
#!/bin/bash
read -p "请输入你的成绩(满分为100分):" num
if [ $num -ge 90 ];then
echo "成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩"
elif [ $num -ge 80 ];then
echo "比较优秀"
elif [ $num -ge 70 ];then
echo "一般一般"
elif [ $num -ge 60 ];then
echo "勉强及格"
else
echo "收拾收拾,回家种地去吧!"
fi
case条件判断结构
- case从变量中取值,如果变量中的值与预设的值匹配,则执行对应的命令
#case语法结构
case $变量名 in
值1)
执行的命令xx;; #如果变量中的值等于值1,则执行的命令
值2)
执行的命令yy;; #如果变量中的值等于2,则执行的命令
...省略其他分支
*)
执行的命令zz;; #如果变量中的值都不是以上的值,则执行的命令
esac
#利用case语句安装软件包
#!/bin/bash
read -p "请输入您要安装的软件包(vsftpd|httpd)": i
case $i in
vsftpd)
yum -y install vsftpd &> /dev/null
echo "vsftpd安装成功" ;;
httpd)
yum -y install httpd &> /dev/null
echo "httpd安装成功";;
*)
echo "请输入范围内的软件包!"
esac
#结合if判断的应用案例
#!/bin/bash
if [ $(rpm -q httpd &> /dev/null;echo $?) -eq 0 ];then
echo 存在
elif [ $(rpm -q vsftpd &> /dev/null;echo $?) -eq 0 ];then
read -p "是否要安装软件包httpd(y/n)": i
case $i in
y)
echo =====正在安装httpd软件=====
b=''
for ((i=0;$i<=20;i++))
do
let jinshu=$i*5
printf "[%-20s]%d%%\r" $b $jinshu
sleep 0.1
b=#$b
done
echo
if [ $(yum -y install httpd &> /dev/null;echo $?) -eq 0 ];then
echo 软件包httpd已经安装成功!
else
echo httpd安装失败
fi;;
n)
echo "退出安装";;
esac
else
if [ $(yum -y install vsftpd &> /dev/null;echo $?) -eq 0 ];then
echo 软件包vsftpd已经安装成功!
fi
fi
vim case.sh
#!/bin/bash
read -p "请输入您喜爱的老师(仓老师|波多老师|小泽老师):" xxoo
case $xxoo in
仓老师)
echo "又白又嫩又水润,上楼右转1号房间!";;
波多老师)
echo "前凸后翘,波涛汹涌,上楼右转2号房间!";;
小泽老师)
echo "肤白貌美大长腿,上楼右转3号房间!";;
*)
echo "老师休假了";;
esac
for循环
for循环处理,根据变量的取值,重复执行xx命令
#for循环语法结构
for 变量名 in 值1 值2 值3 值N...
do
执行的命令
done
#编写循环创建用户脚本
vim user.sh
#!/bin/bash
for user in xiaofang xiaowei jiumei alian
do
useradd $user &> /dev/null
echo "$user 创建成功"
echo 1 | passwd --stdin $user &> /dev/null
echo "$user 密码设置成功,初始密码为“1”"
done
#测试企业的服务器联通性
#!/bin/bash
for i in `seq 254`
do
ping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null
if [ $? -eq 0 ];then
echo "192.168.0.$i UP"
else
echo "192.168.0.$i DOWN"
fi
done
#解释:
-c #ping的次数
-i #指定ping的延迟时间
-W #指定超时时间
chmod u+x ping.sh
./ping.sh
#问题:如何将ping的命令结果存储到文件当中,正确的输出结果与错误的输出结果分别单独存储
#!/bin/bash
for i in `seq 254`
do
ping -c2 -i0.1 -W1 192.168.0.$i >> /dev/null
if [ $? -eq 0 ];then
echo "192.168.0.$i UP" >> up.txt
else
echo "192.168.0.$i DOWN" >> down.txt
fi
done
执行脚本并放入后台
./ping.sh &
while循环
死循环,只要条件成立就重复执行命令
#while循环语法结构
while 条件判断
do
执行的命令
done
#使用while循环编写猜数字脚本
vim while1.sh
#!/bin/bash
num=$[RANDOM%10]
while :
do
read -p "请输入0-10之间的数字:" num1
if [ $num -eq $num1 ];then
echo "恭喜你才对了,奖励一个绝世容颜哇塞女孩!"
exit #退出脚本
else
echo "请继续努力,离哇塞女孩还差一步了,加油!"
fi
done
#利用while循环监控网卡进出口流量
vim net_ens32.sh
#!/bin/bash
while :
do
clear #清屏
ifconfig ens32 | head -2 #显示网卡头两行信息
ifconfig ens32 | grep "RX p" #网卡入口流量
ifconfig ens32 | grep "TX p" #网卡出口流量
sleep 1 #休眠01秒
done
#使用while循环编写一个测试整个网段IP地址的联通性脚本
vim while_ping.sh
#!/bin/bash
i=1 #定义一个变量
while [ $i -le 254 ] #循环判断变量的值小于等于254
do
IP="192.168.0.$i" #定义一个变量
ping -c2 -i0.1 -W1 $IP &> /dev/null #输出结果不要
if [ $? -eq 0 ];then #判断上一条命令的结果,如果上一条命令的结果等于0
echo "$IP UP" #输出主机UP
else
echo "$IP DOWN" #输出主机DOWN
fi
let i++ #对变量的值自加1
done
第十二章:Shell脚本字符串处理
shell函数
在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可称为函数(给一堆命令取一个别名)
函数可以使脚本中的代码更加简洁,增强易读性,提高脚本的执行效率
#函数定义格式1
function 函数名 {
执行的命令1
执行的命令2
...省略更多命令
}
#函数定义格式2
函数名() {
执行的命令1
执行的命令2
...省略更多命令
}
#定义函数
#!/bin/bash
net() {
ifconfig ens32 | grep "RX packets"
ifconfig ens32 | grep "TX packets"
}
while :
do
clear
net #调用函数
sleep 1
done
#定义Nginx status页面
ngx_status="http://127.0.0.1/status"
#判断status页面是否存活
ngx_status_code() {
http_code=`curl -o /dev/null -s -w %{http_code} ${ngx_status}`
if [ ${http_code} == "200" ];then
return 1
else
echo "Nginx status is not running."
fi
}
#获取当前活动的客户端连接数
active() {
ngx_status_code || curl -s ${ngx_status} | grep "Active" | awk '{print $NF}'
}
#获取接收客户端连接的总数量
accepts() {
ngx_status_code || curl -s ${ngx_status} | awk NR==3 | awk '{print $1}'
}
#获取已处理的连接总数量
handled() {
ngx_status_code || curl -s ${ngx_status} | awk NR==3 | awk '{print $2}'
}
#获取客户端请求总数量
requests() {
ngx_status_code || curl -s ${ngx_status} | awk NR==3 | awk '{print $3}'
}
#获取正在读取请求标头的当前连接数量
reading() {
ngx_status_code || curl -s ${ngx_status} | grep "Reading" | awk '{print $2}'
}
#获取正在将响应写回到客户端的当前连接数量
writing() {
ngx_status_code || curl -s ${ngx_status} | grep "Writing" | awk '{print $2}'
}
#获取当前正在等待响应的客户端连接数量
waiting() {
ngx_status_code || curl -s ${ngx_status} | grep "Waiting" | awk '{print $2}'
}
#使用位置变量控制脚本输出
case $1 in
active)
active;;
accepts)
accepts;;
handled)
handled;;
requests)
requests;;
reading)
reading;;
writing)
writing;;
waiting)
waiting;;
*)
echo "Unknown options"
esac
#fork炸弹
vim fork.sh
#!/bin/bash
.() {
.|. &
}
.
chmod u+x fork.sh
./fork.sh
脚本中断及退出
- break #结束整个循环
- continue #结束本次循环,进入下一次循环
- exit #退出脚本
#例子
#!/bin/bash
for i in {1..5}
do
echo $i
done
echo Over
#跳过第三次循环,进入下一次循环
#结束第三次循环,进入下一次循环
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && continue
echo $i
done
echo Over
./for1.sh
1
2
4
5
Over
#结束整个循环
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && break
echo $i
done
echo Over
./for1.sh
1
2
Over
#直接退出脚本
vim for1.sh
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && exit
echo $i
done
echo Over
./for1.sh
1
2
字符串截取
在使用shell脚本完成各种运维任务时,一旦涉及到判断、条件测试等相关操作时往往需要对相关的命令输出进行过滤,提取出符合要求的字符串
-
字符串截取的常用方法:${变量名:起始位置:长度}
-
${}截取字符串时,起始位置是从0开始的
phone=13812345678
echo $phone
13812345678
#统计变量的个数
echo ${#phone}
11
#截取变量的前三位,在截取时包含数字本身
echo ${phone:0:3}
138
#截取后四位
echo ${phone:7:4}
5678
#截取中间四位
echo ${phone:3:4}
1234
#截取一个随机的8位密码
pass=qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789
for i in {1..8}
do
num=$[RANDOM%62]
num1=${pass:num:1}
num2=$num2$num1
done
echo $num2
字符串替换
只替换第一个匹配的结果:${变量名/xx/yy}
替换全部匹配的结果:${变量名//xx/yy}
#只替换匹配到的第一个字符
echo $phone
13812345678
#将匹配到的第一个3替换成4
echo ${phone/3/4}
14812345678
#将匹配到的所有3替换成4
echo ${phone//3/4}
14812445678
字符串掐头去尾
-
从左向右,最短匹配删除:${变量名#*关键词}
-
从左向右,最长匹配删除:${变量名##*关键词}
-
从右向左,最短匹配删除:${变量名%关键词*}
-
从右向左,最长匹配删除:${变量名%%关键词*}
#定义素材
x=`head -1 /etc/passwd`
[root@localhost yunwei]# echo $x
root:x:0:0:root:/root:/bin/bash
#从左到右最短匹配
echo ${x#root}
#从左到右最短匹配,不加*只匹配最左侧的字串
echo ${x#0}
#从左到右最短匹配,加*匹配遇到的第一个字串
echo ${x#*0}
#从左到右最长匹配
echo ${x##0}
root:x:0:0:root:/root:/bin/bash
#从左到右最长匹配
echo ${x##*0}
:root:/root:/bin/bash
#从右到做最短匹配
echo ${x%/bash}
root:x:0:0:root:/root:/bin
#从右到做最短匹配
echo ${x%root*}
root:x:0:0:root:/
#从右向左最长匹配
echo ${x%%root*}
#从右向左最短匹配
echo ${x%0*}
root:x:0:
#从右向左最长匹配
echo ${x%%0*}
root:x:
#把文件以.doc结尾的扩展名,全部改为.txt
touch {1..100}.doc
#字符串去尾方式批量修改文件扩展名
vim file.sh
#!/bin/bash
for i in `ls *.doc`
do
mv $i ${i%doc}txt
done
#字符串替换方式批修改文件扩展名
vim file.sh
#!/bin/bash
for i in `ls *.txt`
do
mv $i ${i/txt/doc}
done
shell数组
#定义数组方式一:数组名=(值1 值2 值3 .. .. 值n)
phone=(13112345678 13212345678 13412345678 13512345678 13612345678)
#按照下标取值,下标从0起使,0就是数组内的第一个值
echo ${x[0]}
echo ${x[0]}
echo ${x[1]}
echo ${x[2]}
echo ${x[3]}
echo ${x[4]}
#获取数组内所有值
echo ${x[@]}
echo ${x[*]}
#向数组内赋值:数组名[下标]=值
phone[5]=13812345678
echo ${b[*]}
#通过数组下载软件包
vim yum.sh
#!/bin/bash
x=(vsftpd httpd gcc openssl-devel pcre-devel)
for i in ${x[@]}
do
yum -y install $i
done
正则表达式
正则表达式使用一串符号描述有共同属性的数据
基本正则符号 | 描述 |
---|---|
^ | 匹配行首 |
$ | 匹配行尾 |
[] | 集合,匹配集合中的任意单个字符 |
[^] | 对集合取反 |
. | 匹配任意单个字符 |
* | 匹配前一个字符出现的任意次数 |
#匹配以什么什么开头的行
grep "^root" /etc/passwd
grep "^#" /etc/fstab
#匹配以什么什么结尾的行
grep "bash$" /etc/passwd
#排除
grep -v "^#" /etc/fstab
grep -v "^#" /etc/fstab | grep -v "^$"
#集合,匹配集合中的任意单个字符
grep "ro[abcotabcd]" /etc/passwd
#集合,对集合中的任意单个字符取反
grep "ro[^abcotabcd]" /etc/passwd
#匹配任意单个字符
grep "roo." /etc/passwd
grep ".oot" /etc/passwd
grep "w.*" /etc/passwd
扩展正则符号 | 描述 |
---|---|
| | 或者 |
#或者
egrep "root|bash" /etc/passwd
netstat -ntlp | egrep "22|80"
作者:叶楠
第十三章:Shell四剑客之sed与awk
四剑客:grep、find、sed、awk
sed流式编辑器
sed是一个非交互的文本编辑器,实现的功能跟vim相同,主要是对文件内容进行输出、删除、替换、复制、剪切、导入、导出等功能
命令格式1:前置命令 | sed [选项] ‘[指令]’ 文件名
命令格式2:sed [选项] ‘[指令]’ 文件名
-
常用选项:
- -n #屏蔽默认输出,默认sed会将所有的输出结果输出到屏幕中,-n只把sed处理的行输出到屏幕
- -i #直接修改文件内容,如果不加-i选项,并不会真正改变文件的内容
-
动作指令:
- p #输出指定的行,如:2,4p 输出第234行,如:2p;4p 打印第2行与第4行
- d #删除指定的行,如:2,4d 删除第234行
- s #字符串替换,如:s/旧字串/新字串/
- g # 全文替换
#打印文件第一行内容
sed -n '1p' /etc/passwd
#打印文件第三行内容
sed -n '3p' /etc/passwd
#打印文件第3行到6行
sed -n '3,6p' /etc/passwd
#打印文件第3行到6行
head -6 /etc/passwd | tail -4
#利用正则表达式匹配以root开头的行(正则表达式要放在//内)
sed -n '/^root/p' /etc/passwd
#匹配以bash结尾的行
sed -n '/bash$/p' /etc/passwd
sed -n '/nologin$/p' /etc/passwd
#=号用于显示行号,例如:打印文件最后一行,打印行号
sed -n '$=' /etc/passwd
#打印以root开头的行号
sed -n '/^root/=' /etc/passwd
#拷贝文件练习
cp /etc/passwd /opt/test
#删除文件2到4行
sed '2,4d' test | wc -l
#使用i选项直接修改源文件
sed -i '2,4d' test
#使用分号分隔
sed -i '10d;12d' test
sed -n '$=' test
sed -n '/sync/p' test
#取反删除
sed '/sync/!d' 1.txt
#-r支持扩展正则过滤方式
sed -r '/sync|apache/!d' test
#空行
sed -n '/^$/p' /etc/fstab
#准备素材
sed -n p num.txt
2021 2020 2019 2018
2021 2021 2020 2019
2021 2022 2021 2020
#替换文件每一行匹配到的第一个字串
sed -n 's/2021/xxxx/p' num.txt
sed -i 's/2021/xxxx/' num.txt
#替换文件每一行匹配到的第二个字串
sed 's/2021/xxxx/2' num.txt
sed -n 's/root/xxxx/2p' test
root:x:0:0:xxxx:/root:/bin/bash
sed -n 's/root/xxxx/3p' test
root:x:0:0:root:/xxxx:/bin/bash
#替换文件每一行匹配到的所有指定字串
sed -n 's/root/xxxx/gp' test
xxxx:x:0:0:xxxx:/xxxx:/bin/bash
#将匹配到的第一个字串替换成空
sed 's/2021//' xx.txt
#将匹配到的第=二字串替换成空
sed -n 's/root//2p' test
root:x:0:0::/root:/bin/bash
sed -n 's/root//3p' test
root:x:0:0:root:/:/bin/bash
#替换符可以使用任意的特殊符号
sed -n 's#root##p' test
#将文件中/bin/bash替换成/sbin/nologin
sed -n 's/\/bin\/bash/\/bin\/sh/gp' test
sed -n 's,bin/bash,sbin/nologin,p' test
#使用sed给文件1-3行批量添加注释
sed -n '1,3s/^/#/p' test
sed -i '1,3s/^/#/' test
sed -n '1,3p' test
#批量去除1-3行的注释
sed -n '1,3s/^#//p' test
sed -i '1,3s/^#//p' test
sed -n '1,3p' test
#将文件中所有的数字替换成空
sed -n 's/[0-9]//gp' test
#将文件中所有的英文字母替换成空
sed -n 's/[a-Z]//gp' test
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示例:
#手动指定以:作为分隔,打印文件第一列
awk -F: '/root/ {print $1}' test
#打印文件第一列和第七列(默认没有空格与tab键作为分隔符,打印文件所有内容)
awk -F: '/root/ {print $1,$7}' test
#通过[]集合匹配多种单个字符作为分隔符,打印用户名与解释器字段
awk -F[:/] '{print $1,$10}' test
#通过正则表达式过滤以root开头的行
awk -F: '/^root/{print}' test
#通过正则表达式过滤以root开头的行,打印第1列与第7列
awk -F: '/^root/ {print $1,$7}' test
#打印文件每一行与每一行的列数,NR文件当前行号,NF文件当前列数
awk -F: '{print NR,NF}' test
#打印文件每一行与每一行的列数,并打印最后一列
awk -F: '{print NR,NF,$NF}' test
#通过常量打印执行的列
awk -F: '{print $1,"用户的解释器为:",$7}' test
root 用户的解释器为: /bin/bash
#匹配第一列包含root的行
awk -F: '$1~/root/ {print $1,$7}' test
#排除第7列noloogin的行,打印第1列与第7列
awk -F: '$7!~/nologin/{print $1,$7}' /etc/passwd
#利用扩展正则过滤,以root或者adm开头的行,打印第1列与第7列
awk -F: '/root|adm/{print $1,$7}' /etc/passwd
awk使用数值/字符串比较设置条件
- 等于: ==
- 不等于: !=
- 大于: >
- 大于等于: >=
- 小于: <
- 小于等于:<=
#打印行号等于3
awk 'NR==3{print}' test
#使用sed更加方便打印某一行
sed -n '3p' test
#打印文件中第3列大于等于1000,打印第1列,第3列,第7列
awk -F: '$3>=1000{print $1,$3,$7}' /etc/passwd
#打印文件中第三列小于1000,打印第1列,第3列,第7列
awk -F: '$3<1000{print $1,$3,$7}' /etc/passwd
#打印文件中第3列大于500并且小于1000,打印第1列,第3列,第7列
awk -F: '$3>500 && $3<1000 {print $1,$3,$7}' /etc/passwd
#打印第一列不等于root的行
awk -F: '$1!="root"{print}' /etc/passwd
awk过滤时机:awk ‘BEGIN{指令} {指令} END{指令}’ 文件名
- BEGIN{指令} #读取文件内容之前执行指令,指令执行一次,行前处理
- {指令} #读取文件过程中执行,指令逐行执行,读一行,执行一次
- END{指令} #读取文件内容结束后执行指令,指令执行一次,行后处理
#BEGIN{指令}行前处理
awk 'BEGIN{print "正在处理中"}'
正在处理中
#通过awk统计系统里使用bash解释器的用户个数?
awk 'BEGIN{x=0}/bash$/{x++}END{print x}' /etc/passwd
awk '/bash$/{x++}END{print x}' /etc/passwd
awk分支结构
- if单分支格式:if(条件){指令}
- if双分支格式:if(条件){指令}else{指令}
#if单分支统计passwd文件中UID大于或等于1000的用户个数
awk -F: '{if($3>=1000){num++}} END{print num}' /etc/passwd
#if双分支统计passwd文件中UID大于等于1000的用户,和小于1000的用户个数
awk -F: '{if($3>=1000){num1++} else{num2++}} END{print num1,num2}' /etc/passwd
awk数组
- 定义数组格式1:数组名[下标]=值
- 定义数组格式2:数组名=值
- 数组的用法:for(变量名 in 数组名) {print 数组名[变量]}
#awk定义数组方式
awk 'BEGIN{x[0]=10;x[1]=20;print x[0],x[1]}'
#awk定义数组方式
awk 'BEGIN{x[0]++;print x[0]}'
awk循环结构
- 命令格式:for(变量名 in 数组名){print 数组名[变量]}
awk 'BEGIN{a[0]=00;a[1]=11;a[2]=22;for(i in a){print i,a[i]}}'
awk命令格式2:前置命令 | awk [选项] ‘条件{指令}’
#通过awk打印剩余内存
free -h | grep Mem | awk '{print $4}'
free -h | awk '/Mem/{print $4}'
#用awk写一个监控脚本,监控网卡的进出口流量
vim while_liuliang.sh
#!/bin/bash
while :
do
clear
ifconfig ens32 | awk '/inet /{print "IP:",$2}'
ifconfig ens32 | awk '/RX p/{print "入口流量:",$6,$7}'
ifconfig ens32 | awk '/TX p/{print "出口流量:",$6,$7}'
sleep 0.1
done
#使用awk过滤系统根分区使用情况
df -h / | awk '/\/$/{print $4}'
df -h / | awk '/\/$/{print $4}' | awk -FG '{print $1}'
#过滤根分区剩余空间与物理内存空间
vim df_free.sh
#!/bin/bash
df -h | grep '/$' | awk '{print "根分区剩余空间:",$4}'
free -h | grep Mem | awk '{print "物理内存剩余空间:", $4}'
#通过awk统计用户当前登录的终端数量
who | awk '{ip[$1]++}END{for(i in ip)print i,ip[i]}'
作者:叶楠
第十四章:计划任务与系统安全
cron周期性计划任务
cron周期性计划任务用来定期执行程序,目前最主要的用途是定期备份数据
- 软件包名:cronie、crontabs
- 服务名:crond
- 日志文件:/var/log/cron
crontab:用于管理计划任务
- crontab -e -u 用户名 #编写计划任务
- crontab -l -u 用户名 #查看计划任务
- crontab -r -u 用户名 #清除所有计划任务
#软件包默认系统自动安装
rpm -q cronie
cronie-1.4.11-19.el7.x86_64
#服务默认随机自启
systemctl status crond
#cron定义时间格式
* * * * * 执行的命令
分 时 日 月 周
分钟:从0到59之间的整数
小时:从0到23之间的整数
日期:从1到31之间的整数
月份:从1到12之间的整数
星期:0~6之间的整数,0代表周日
* #每分,每时,每天,每月,每周
, #分隔多个不连续的时间
- #指定连续时间范围
/ #指定执行任务的时间间隔
#每周5凌晨2点执行一个任务
00 2 * * 5 xx命令
#每天凌晨2点30分执行一个任务
30 2 * * * xx命令
#日期跟星期不能同时定义,发生矛盾(没有这么定义的!)
30 2 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命令
#每两小时执行一个任务
00 */2 * * * xx命令
#每两分钟执行一个任务
*/2 * * * * xx命令
#每一分钟执行一个任务
crontab -e
*/1 * * * * date >> /opt/date.txt
cat /opt/date.txt
2021年 05月 23日 星期日 17:30:02 CST
#每周6凌晨3:30分备份/var/log/日志文件
crontab -e
30 3 * * 6 tar -czf `date +%F`-log.tar.gz /var/log/*.log
#查看计划任务
crontab -l
30 3 * * 6 tar -czf `date +%F`-log.tar.gz /var/log/*.log
#清除计划任务
crontab -r
crontab -l
SELinux系统内核安全机制
-
Security-Enhanced Linux 美国NSA国家安全局主导开发,一套增强Linux系统安全的强制访问控制体系(内核防火墙)
-
集成到Linux内核(2.6及以上)针对用户、进程、目录和文件提供了预设的保护策略,以及管理工具
-
SELinux运行模式
- enforcing #强制模式
- permissive #宽松模式
- disabled #禁用模式
-
SELinux运行模式切换
- 查看当前运行模式:getenforce
- 临时切换运行模式:setenforce 1|0 #1强制模式,0宽松模式
#查看当前运行模式
[root@localhost ~]# getenforce
Enforcing #默认为强制模式
#切换运行模式为宽松模式
[root@localhost ~]# setenforce 0
[root@localhost ~]# getenforce
Permissive
#切换运行模式为强制模式
[root@localhost ~]# setenforce 1
[root@localhost ~]# getenforce
Enforcing
SELinux配置文件:/etc/selinux/config
#永久修改运行模式
[root@localhost ~]# vim /etc/selinux/config
...
SELINUX=disabled
常见协议及端口
- http:超文本传输协议(明文协议) 默认端口:80
- https:安全的超文本传输协议(加密协议) 默认端口:443
- ftp:文件传输协议 默认端口:20(数据端口(21(命令端口)
- tftp:简单的文件传输协议 默认端口:69
- DNS:域名解析协议 默认端口:53
- telnet:远程管理协议 默认端口:23
- smtp:用户发邮件协议 默认端口:25
- pop3:用户收邮件协议 默认端口:110
- ssh:远程连接协议 默认端口:22
- /etc/services 文件记录协议及端口信息
环境准备
#安装httpd与vsftpd服务
[root@localhost ~]# rpm -q httpd
#启动服务
[root@localhost ~]# systemctl start httpd
#查看运行状态
[root@localhost ~]# systemctl status httpd
第十五章:系统安全防护之防火墙
netfilter工作在主机或网络的边缘,对于进出本主机或网络的报文根据事先定义好的检查规则作匹配检测,对于能够被规则所匹配到的报文做出相应的处理
防火墙的种类:
- 软件防火墙:软件技术实现数据包过滤
- 硬件防火墙:硬件设备,实现数据包过滤
防火墙类型:
- 主机型防火墙:保护自己本机应用程序
- 网络防火墙:保护内部其他服务器应用程序
软件型防火墙:netfilter是Linux内核自带一个模块,网络过滤器
CentOS7系统:默认使用的防火墙管理工具firewalld
CentOS6系统:默认使用的防火墙管理工具iptables
firewalld防火墙
- 管理工具:firewalld-cmd
- 防火墙预设安全区域
- public:仅允许访问本机的sshd、DHCP、ping等少量服务
- trusted:允许任何访问
- block:拒绝任何来访请求,有明确回应
- drop:拒绝任何来访请求,没有任何回应(丢弃)
#开启防火墙
systemctl start firewalld
#查看默认区域
firewall-cmd --get-default-zone
public
#修改默认区域
firewall-cmd --set-default-zone=区域名
#将默认区域修改为block
firewall-cmd --set-default-zone=block
success
firewall-cmd --get-default-zone
block
#将默认区域修改为drop
firewall-cmd --set-default-zone=drop
success
firewall-cmd --get-default-zone
drop
#将默认区域修改为public
firewall-cmd --set-default-zone=public
success
firewall-cmd --get-default-zone
public
#查看区域规则
firewall-cmd --zone=区域名 --list-all
#查看public所有规则
firewall-cmd --zone=public --list-all
public (active)
target: default #默认区域
icmp-block-inversion: no
interfaces: ens32
sources:
services: ssh dhcpv6-client #允许访问的服务
#为public区域添加http协议(临时),使用 --add-service=服务名
firewall-cmd --zone=public --add-service=http
success
firewall-cmd --zone=public --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens32
sources:
services: ssh dhcpv6-client http #添加http协议
#为public区域永久添加http协议(必须要先临时添加在执行永久添加)
#若针对永久配置需添加 --permanent
firewall-cmd --permanent --zone=public --add-service=ftp
success
#为public添加ftp协议
firewall-cmd --zone=public --add-service=ftp
success
firewall-cmd --zone=public --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens32
sources:
services: ssh dhcpv6-client http ftp #添加ftp协议
#临时移除
firewall-cmd --zone=public --remove-service=ftp
#永久移除
firewall-cmd --permanent --zone=public --remove-service=http
#永久修改需重新加载防火墙配置
firewall-cmd --reload
针对IP地址规则配置
#使用 --add-source=网段地址
#单独拒绝某一个IP(临时)
firewall-cmd --zone=block --add-source=192.168.0.24
firewall-cmd --zone=block --list-all
block (active)
target: %%REJECT%%
icmp-block-inversion: no
interfaces:
sources: 192.168.0.24
#删除规则:--remove-source
firewall-cmd --zone=block --remove-source=192.168.0.24
firewall-cmd --zone=block --list-all
#删除public区域的ftp协议
firewall-cmd --zone=public --remove-service=ftp
success
[root@localhost ~]# firewall-cmd --zone=public --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens32
sources:
services: ssh dhcpv6-client http
防火墙端口映射
本地应用的端口重定向(端口1 > 端口2)从客户机访问 端口1 的请求,自动映射到本机端口2
#当有人访问5432端口时,映射到本机的80端口
firewall-cmd --zone=public --add-forward-port=port=5432:proto=tcp:toport=80
#命令解释:
--add--forward #添加转发端口
port=port=5432 #指定转发的端口
proto=tcp #指定tcp协议
toport=80 #指定目标端口
firewall-cmd --zone=public --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens32
sources:
services: ssh dhcpv6-client http
ports:
protocols:
masquerade: no
forward-ports: port=5432:proto=tcp:toport=80:toaddr=
iptables框架
表里存放链,链里存放防火墙规则
iptables的4表
**filter:**是iptables的默认表,用于对数据包进行过滤
包含三个链:INPUT,OUTPUT,FORWARD
**nat:**地址转换表,不能过滤数据包,用于修改数据包中的源IP
与目的IP
和端口映射
包含三个链:PREROUTING,POSTROUTING,OUTPUT
**mangle:**标记表,主要功能是修改数据包的一些标志位,以便对数据包进行策略路由
包含五个链:PREROUTING,FORWARD,POSTROUTING,INPUT,OUTPUT决定是否跟踪数据包
**raw:**状态跟踪表,用于跟踪数据包
包含两个链:OUTPUT,PREROUTING
iptables的5链
INPUT链
——进来
的数据包应用此规则链中的规则OUTPUT链
——外出
的数据包应用此规则链中的规则FORWARD链
——转发
数据包时应用此规则链中的规则PREROUTING链
——对数据包作路由选择前
应用此链中的规则POSTROUTING链
——对数据包作路由选择后
应用此链中的规则
iptables命令格式
防火墙特性:从上到下逐条匹配,匹配即停止
防火墙特性:没有被规则匹配到,按照默认规则处理
**命令格式:**Iptables [-t 表名] 选项 [链名] [条件] [-j 目标操作]
-
添加规则:
- -A #
追加
一条防火墙规则至链的末尾
- -I #插入一条防火墙规则至链的
开头
- -D #
删除
一条防火墙规则
- -A #
-
查看规则:
- -L #查看iptables所有规则,与-n连用
- -n #以数字形式显示地址、端口等信息,与-L连用
- –line-numbers #查看规则时,显示规则的行号
-
删除规则:
- -D #删除链内指定的序号(或内容)的一条规则
- -F #清空指定表的所有规则
-
默认规则:
- -P #为指定的链设置默认规则
目标操作
- ACCEPT:允许通过/放行
- DROP:直接丢弃,不给出任何回应
- REJECT:拒绝通过,有明确回应
iptables防火墙规则的条件
-
协议匹配:-p #协议名称
-
地址匹配:-s 源地址、-d 目标地址
-
接口匹配:-i 接受数据的网卡、-o 发送数据的网卡
-
端口匹配:–sport 源端口号、–dport 目标端口号
创建规则注意事项
- 可以不指定表,默认为filter表
- 如果没有找到匹配条件,执行防火墙默认规则
主机型防火墙规则配置
#停止本机的firewalld防火墙
systemctl stop firewalld
systemctl disable firewalld
#安装iptables服务
yum -y install iptables-services
systemctl start iptables
#拒绝icmp访问
iptables -t filter -I INPUT -p icmp -j REJECT
#查看规则
iptables -L -n --line-numbers
#测试icmp访问
ping 192.168.0.80
iptables -t filter -I INPUT -p icmp -j DROP
iptables -t filter -I INPUT -p icmp -j ACCEPT
#清空某一条规则(默认为filter表)
iptables -t filter -D INPUT 3
#清空指定链内所有规则(默认为filter表所有规则)
iptables -F INPUT
iptables -F
#清空其他表所有规则
iptables -t nat -F
iptables -t raw -F
iptables -t mangle -F
设置防火墙默认规则
#查看filter表
iptables -t filter -nL
#允许22号端口被访问
iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -nL
#将filter表INPUT链默认规则修改为DROP(默认规则不允许使用REJECT)
iptables -t filter -P INPUT DROP
iptables -nL
#将默认规则修改为ACCEPT
iptables -t filter -P INPUT ACCEPT
#设置防火墙拒绝所有80端口的访问
iptables -t filter -I INPUT -p tcp --dport 80 -j REJECT
#查看规则
iptables -nL
iptables -F
#单独拒绝某个IP的任何访问
iptables -t filter -I INPUT -s 192.168.0.24 -j REJECT
#单独拒绝某个IP不允许访问本机的某个服务(端口)
iptables -I INPUT -s 192.168.0.24 -p tcp --dport 80 -j REJECT
#设置防火墙拒绝某个网段
iptables -t filter -I INPUT -s 192.168.1.0/24 -j REJECT
#查看规则
iptables -nL
防火墙扩展
命令格式:iptables 选项 链名 -m 扩展模块 --具体扩展条件 -j 动作
#根据MAC地址封锁主机,安装nmap扫描获取地方IP的MAC地址
yum -y install nmap
#获取对方主机MAC地址
nmap 192.168.28
#通过MAC地址限制对方访问
iptables -t filter -I INPUT -p tcp --dport 80 -m mac --mac-source 00:0C:29:D5:29:0F -j REJECT
基于多端口设置过滤规则
#multiport :多端口模块
iptables -t filter -I INPUT -p tcp -m multiport --dports 20,21,80,443 -j ACCEPT
#根据IP范围设置封锁规则
iptables -t filter -I INPUT -p tcp --dport 80 -m iprange --src-range 192.168.1.20-192.168.1.30 -j REJECT
#iprange模块:ip范围模块
#--src-range:源IP
所有iptables规则都是临时规则,如果需要永久保留规则需要执行如下命令
service iptables save
网络型防火墙环境规划
#防火墙主机开启路由转发功能(转发流量)
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
#加载配置立即生效
sysctl -p
net.ipv4.ip_forward = 1
#关闭httpd服务
systemctl stop httpd
#node01安装httpd
yum -y install httpd
#创建一个访问的页面文件
echo 'hello linux' > /var/www/html/index.html
#访问测试
curl 192.168.1.110
防火墙主机配置规则:拒绝192.168.0.25访问80端口
iptables -I FORWARD -s 192.168.1.10 -p tcp --dport 80 -j DROP
#客户端192.168.1.30访问测试:
curl http://192.168.0.20
#拒绝所有客户端地址访问内网80端口
iptables -t filter -I FORWARD -p tcp --dport 80 -j REJECT
iptables -F
配置SNAT实现共享上网
通过防火墙规则,允许局域网中的主机访问外网
主机名 | 网卡、IP地址、网关 |
---|---|
内部主机:client25 | ens32:192.168.1.25,网关:192.168.1.100 |
内部防火墙:iptables | ens32外网IP:192.168.0.80,ens34内网IP:192.168.1.100 |
外部主机:web26 | ens32:192.168.0.26,网关:192.168.0.80 |
#实现192.168.1.25转换为192.168.0.80
iptables -t nat -I POSTROUTING -s 192.168.1.0/24 -p tcp -j SNAT --to-source 192.168.0.80
#POSTROUTING:路由后链
#-s:指定源地址为192.168.1.0网段的地址
#-p:想要通过tcp协议
#--dport:访问目标的80端口时
#-j:SNAT转换
#--to-source:转换源地址为192.168.0.26
#web1动态查看访问日志
tail -f /var/log/httpd/access_log
client 192.168.1.25访问网站
curl http://192.168.0.26
作者:叶楠
第十六章:用户提权与OpenSSH安全
sudo用户提权
管理员提前为用户设置执行权限许可,被授权用户有权执行命令权限
-
配置文件:/etc/sudoers
/etc/sudoers
visudo
-
命令格式:sudo 特权命令
修改/etc/sudoers文件,为lisi用户授予相关命令执行权限,允许通过systemctl工具来管理系统服务
#/etc/sudoers配置文件可以用vim编辑文件,或者使用visudo命令修改
visudo
.. ..
root ALL=(ALL) ALL
lisi ALL=(root) /bin/systemctl
解释:授权lisi用户以root身份执行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 haha
uid=1001(haha) gid=1001(haha) 组=1001(haha)
#修改haha用户密码
[lisi@master ~]$ sudo passwd haha
#为sudo机制启用日志记录,以便跟踪sudo执行操作
[root@master ~]# visudo
.. ..
Defaults logfile="/var/log/sudo.log" #手动添加
.. ..
#普通用户执行sudo命令
[lisi@master ~]$ sudo systemctl start httpd
#查看日志是否记录
[root@master ~]# cat /var/log/sudo.log
Sep 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-keygen
#查看密钥文件
[root@localhost ~]# ls .ssh
id_rsa id_rsa.pub
#将公钥拷贝至其他主机
[root@localhost ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.0.27
#其他主机查看公钥文件
[root@host-27 ~]# ls .ssh
authorized_keys
#验证是否实现密钥认证登录
[root@localhost ~]# ssh 192.168.0.27
Last 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 /opt
fstab test.txt
提高ssh服务安全性
配置文件:/etc/ssh/sshd_config
[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 #定义账号黑名单
本地解析文件:
-
Linux系统:/etc/hosts
192.168.x.x 名称
-
windows系统:C:\Windows\System32\drivers\etc
-
格式:IP 名称
作者:叶楠
第十七章:文件共享服务FTP与NFS
文件共享服务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:华盛顿大学研发的一款FTP软件
- proftpd:专业的FTP软件
- pureftp:纯粹的FTP软件
- vsftpd:非常安全的ftp软件
- ServU:windows里的一款FTP软件
- FileZilla:windows里的一款FTP软件,Linux系统也可以使用
客户端访问ftp服务器工具:
- ftp
- lftp、lftpget
- wget
- curl
- FileZilla:windows客户端工具,可从软件商店直接下载
- 浏览器
vsftpd介绍
vsftpd(very secure ftp daemon)非常安全的FTP守护进程
是一款运行在Linux操作系统上开源且免费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匿名用户模式
#修改FTP服务端主机名
[root@ftp-server ~]# hostnamectl set-hostname ftp-server
#安装软件
[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
#客户端访问FTP服务端
[root@client ~]# ftp 192.168.0.80
[root@client ~]# lftp 192.168.0.80
#匿名用户权限介绍
[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 #本地用户上传文件默认权限为755
37 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的连接,默认没开启,改为yes
126 pam_service_name=vsftpd #启用pam认证的文件名称,路径为/etc/pam.d/vsftpd
127 userlist_enable=YES #是否启用控制名单文件,yes启用,no不启用,文件为/etc/vsftpd/user_list,如果启用控制名单功能,需要指定该文件为黑名单|白名单
128 userlist_deny=no #yes拒绝user_list文件中用户登录ftp服务器(黑名单),no允许登录(白名单)
max_clients= #限制最大并发连接数量
vsftpd虚拟用户模式
需要数据库支持!
第十八章:NFS网络附加存储
NFS(Network File System)和FTP(File Transfer Protocol)都是用于文件共享的协议,但它们有一些区别:
- 目的:NFS主要用于在网络上共享文件系统,而FTP主要用于在网络上传输文件。
- 速度:NFS通常比FTP快,因为它不需要建立连接和认证。
- 安全性:FTP可以提供比NFS更好的安全性,因为它支持加密传输和用户认证。
- 实现:NFS是在操作系统内核中实现的,而FTP需要一个专门的服务器软件来运行。
- 文件访问:NFS可以让多个客户端同时访问同一个文件,而FTP只能支持单个客户端的文件传输。
总体来说,NFS适合在局域网内共享文件系统,而FTP则适合在广域网上进行文件传输。
NFS(Network File System)网络文件系统 , 是一种基于TCP/UDP传输协议的文件共享服务
NFS基于C/S架构,服务端启用协议将文件共享到网络上,然后允许本地NFS客户端通过网络挂载服务端共享的文件。
-
NFS协议:端口号 2049
-
软件包:nfs-utils
-
服务名:nfs
-
配置文件:/etc/exports
NFS服务端配置
#安装nfs服务端软件包
[root@localhost ~]# yum -y install nfs-utils
#启动nfs服务
[root@localhost ~]# systemctl start nfs
[root@localhost ~]# systemctl enable nfs
#提前添加一块硬盘并创建成逻辑卷
vgcreate myvg /dev/sdb
lvcreate -L 49.9G -n mylv myvg
mkfs.xfs /dev/myvg/mylv
#创建共享目录
mkdir /nfs-public
mount /dev/myvg/mylv /nfs-public/
#修改nfs主配置文件:/etc/exports
[root@localhost ~]# vim /etc/exports
/nfs-public 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.26
Export 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:/nfs-public /opt/public
服务器地址:文件夹路径 挂载点
[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.txt
touch: 无法创建"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]# ls
xx.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]$ ls
lisi.txt xx.txt
[lisi@client upload]$ rm -rf xx.txt
rm: 无法删除"xx.txt": 不允许的操作
#客户端实现开机挂载配置:/etc/fstab
[root@localhost]# vim /etc/fstab
192.168.0.26:/xxx /mnt/xxx nfs defaults,_netdev 0 0
服务器地址:文件夹路径 挂载点 文件系统 defaults,_netdev 0 0
#解释:_netdev:指定nfs是网络设备
如果nfs服务器没有开启,客户端会一直尝试连接挂载此时其他的进程就无法继续进行。
NAS(网络附加存储)存储模式中的文件共享服务:
-
samba文件共享服务:支持跨平台
-
FTP文件共享服务:支持跨平台
-
NFS文件共享服务:支持跨平台
DAS存储(直连存储):直接附加在电脑主板上的硬盘
SAN存储(存储区域网络):块级别存储,把自己电脑上的硬盘共享给其他主机
对象存储:没有任何规律的数据(短视频、图片、音频)
第十九章: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+inotify数据同步
rsync远程同步
rsync(Remote Sync): 是一款开源,快速,多功能的可实现本地或远程主机数据同步与增量备份的优秀工具。(数据同步与备份的工具)可使本地主机不同分区或目录之间及本地和远程两台主机之间的数据快速同步,远程备份等功能 。
在同步备份时,默认情况下,rsync通过其独特的“quick check”算法,仅同步大小或者最后修改时间发生变化的文件或目录(也可根据权限,属主等变化同步,需要制定参数)。甚至是只同步一个文件里变化的内容部分,所以可以实现快速的同步数据的功能。
提示:传统的cp、scp、tar等工具每次均为完全备份,而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(修改),create(创建),delete(删除),attrib(权限) |
配置实时监控
#监控本机/test1目录
[root@master ~]# vim rsync.sh
#!/bin/bash
while inotifywait -rq -e modify,create,delete,attrib /test1/ &> /dev/null
do
rsync -az --delete /test1/ root@192.168.0.34:/opt &> /dev/null
done
#实现从本地到远程的Web目录推送
#源目标:/var/www/html
#!/bin/bash
IPADDR=10.0.6.191
FROM_DIR="/var/www/html/"
RSYNC_CMD="rsync -za --delete $FROM_DIR root@$IPADDR:/var/www/html"
while inotifywait -rqq -e modify,move,create,delete,attrib $FROM_DIR #q不显示输出
do
$RSYNC_CMD
done &
第二十章:Ansible介绍及部署
Ansible是2013年推出的一款IT自动化DevOps软件,基于Python语言开发。
Ansible基于Paramiko实现SSH协议链接通讯,默认只要被管理节点开启SSH服务,Ansible就可以管理远程主机,使用Ansible不需要额外在客户端主机安装Agent程序(只需要ssh)。
Ansible模块化设计,并且模块丰富,支持自定义模块,自定义模块可用任何语言编写。
Ansible基于PyYAML模块支持Playbook,可以通过Playbook完成可重复的复杂工作。
Ansible Roles(角色)比Playbook更加适合部署复杂的大型的环境(OpenStack、K8s等)
Ansible核心组成
常见的批量管理工具介绍
-
Ansible:基于Python语言开发,无需客户端,轻量级批量管理工具
-
SaltStack:基于Python语言开发,C/S架构
-
Puppet:淘汰学习成本高基于Ruby语言开发==冷门
-
Chef:淘汰学习成本高基于Ruby语言开发==冷门
实验环境准备
实验机3台,1台为Ansible管理主机,2台为被管理主机
主机名 | 角色 | 系统环境 | 硬件配置 |
---|---|---|---|
Ansible | 管理主机 | CentOS 7.6 | 2C/4G |
node01 | 被管理主机 | CentOS 7.6 | 2C/4G |
node02 | 被管理主机 | CentOS 7.6 | 2C/4G |
三台主机修改对应的主机名称
hostnamectl set-hostname Ansible --static
hostnamectl set-hostname node1
hostnamectl set-hostname node2
提示:接下来的所有操作都在Ansible管理主机执行。
管理节点修改/etc/hosts文件实现本地解析(企业环境有内部的DNS服务器)
vim /etc/hosts
...
192.168.0.30 node01
192.168.0.31 node02
管理节点与被管理节点实现SSH密钥认证
ssh-keygen
传递公钥到被管理节点并验证SSH免密登录
[root@ansible-server ~]# for IP in node01 node02
do
ssh-copy-id $i
done
安装Ansible软件包
安装ansible软件包需要epel源,本实验配置了阿里的epel源和阿里的Base源(Base源用于安装ansible所需依赖)
下载阿里Base源与epel源
# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
安装ansible软件包
yum -y install ansible
查看ansible版本信息
ansible --version
定义Ansible主机清单
- ansible主配置文件:/etc/ansible/ansible.cfg
- ansible默认清单文件:/etc/ansible/hosts
编辑清单文件定义主机组
vim /etc/ansible/hosts
...
[websrvs]
node[01:02]
列出指定组内主机列表
[root@ansible-server ~]# ansible websrvs --list-host
hosts (2):
node01
node02
Ansible-doc命令介绍
ansible-doc 模块文档命令
-
常用选项:
-l #列出所有模块列表
-s #查看模块帮助信息
Ansible命令格式介绍
常用命令格式:ansible 组名/主机 [-m 模块名] [-a 具体操作]
使用ping模块测试websrvs组主机连通性
[root@ansible-server ~]# ansible websrvs -m ping
Ansible返回值颜色表示
- 绿色:命令执行成功了,对远程主机没有造成改变(远程主机没有发生变化)
- 黄色:命令执行成功了,对远程主机造成了修改(远程主机发生了变化)
- 红色:代表你的命令执行失败或者是有异常,反正就是错误了
- 粉色:代表命令执行后发出的警告,给我们一些建议(可以忽略)
第二十一章:Ansible常用模块介绍
command 模块
-
command模块为默认模块,用于远程执行命令(命令模块)
注意:使用command模块在远程主机中执行命令时,不会经过远程主机的bash处理,在使用command模块时,如果需要执行的命令中含比如”<“, “>”, “|”, “;” 和 “&” 这些符号时,这些符号的功能也会失效
-
常用参数:
- chdir:此参数表示执行命令之前,会先进入到指定的目录中
- creates: 此参数表示文件如果存在于远程主机中,则不执行对应命令,如果不存在,才执行
- removes:此参数表示文件如果不存在于远程主机中,则不执行对应命令,如果存在 ,才执行
#chdir参数表示执行命令之前,会先进入到指定的目录中
ansible websrvs -m command -a 'chdir=/root/ ls'
#creates参数表示如果/etc/passwd文件存在于远程主机中,则不执行对应命令,如果不存在,才执行”touch”命令
ansible websrvs -m command -a 'creates=/opt/test.txt touch /opt/test.txt'
#演示:creates参数在文件不存在情况下才会执行“touch”命令
ansible websrvs -m command -a 'creates=/opt/passwd touch /opt/passwd'
#removes参数表示如果/opt/abc文件不存在,就不执行“mv”命令,如果文件存在则执行“mv”命令
ansible websrvs -m command -a 'removes=/opt/test.txt mv /opt/test.txt /root/'
#演示:removes参数如果/opt/passwd文件不存在,就不执行“mv”命令
ansible websrvs -m command -a 'removes=/opt/passwd mv /opt/passwd /root/'
ansible websrvs -m command -a 'hostname'
ansible websrvs -m command -a 'ip a s ens32'
ansible websrvs -a 'uname -r' #查看内核信息
ansible websrvs -a 'free -h' #查看内存信息
shell 模块
shell 模块,远程执行命令模块,和command模块类似,区别在于shell模块通过bash程序处理命令
-
常用参数
- cmd:此参数指定用于执行的命令(用于在Playbook剧本中)
- chdir:此参数表示执行命令之前,会先进入到指定的目录中
- creates: 此参数表示文件如果存在于远程主机中,则不执行对应命令,如果不存在,才执行
- removes:此参数表示文件如果不存在于远程主机中,则不执行对应命令,如果存在 ,才执行
提示: shell模块中chdir、creates、removes参数的作用与command模块中的作用都是相同的,此处不再举例
-
shell 模块示例:
#查看/etc/passwd文件,并通过管道符传递给“wc -l”统计文件行数
ansible websrvs -m shell -a 'cat /etc/passwd | wc -l'
#查看/etc/passwd文件,并通过“>”将文件内容重定向至/opt/passwd文件中
ansible websrvs -m shell -a 'cat /etc/passwd > /opt/passwd'
#通过chdir参数进入/opt/目录,执行“ls”
ansible websrvs -m shell -a 'chdir=/opt/ ls'
#通过chdir参数进入/opt目录,执行“cat”查看passwd文件内容
ansible websrvs -m shell -a 'chdir=/opt/ cat passwd'
#查看主机名
ansible websrvs -m shell -a 'hostname'
#查看内核信息
ansible websrvs -m shell -a 'uname -r'
#查看ens32网卡的IP地址信息
ansible websrvs -m shell -a 'ip a s ens32 | grep inet'
#查看内存使用信息
ansible websrvs -m shell -a 'free -h'
#查看分区使用信息
ansible websrvs -m shell -a 'df -h'
#关闭防火墙&&设置开机不自起
ansible websrvs -m shell -a 'systemctl stop firewalld && systemctl disable firewalld'
script 模块
script 模块用于远程执行shell脚本,脚本存放在ansible主机本地,不需要拷贝到远程主机
- 常用参数:
- chdir:此参数表示执行命令之前,会先进入到指定的目录中
- creates: 此参数表示文件如果存在于远程主机中,则不执行对应命令,如果不存在,才执行命令
- removes:此参数表示文件如果不存在于远程主机中,则不执行对应命令,如果存在 ,才执行命令
提示: script模块中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:此状态用于启动服务
#启动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:此状态用于重启服务
#重启服务 [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为必须参数
#在ansible本地主机创建文件 [root@ansible-server ~]# touch /tmp/test.txt #将本地/tmp/test.txt文件拷贝至ftp组内主机的/var/ftp目录下 [root@ansible-server ~]# ansible websrv -m copy -a 'src=/root/index.html dest=/var/www/html' [root@ansible-server ~]# ansible websrv -m shell -a 'ls /var/ftp'
force:此参数当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变
#使用force参数指定当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,不执行覆盖 ansible ftp -m copy -a 'src=/root/hello dest=/opt force=no'
backup:此参数当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机
#使用backup参数指定当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,对远程主机文件先进行备份 ansible ftp -m copy -a 'src=/root/hello dest=/opt backup=yes'
owner:此参数指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错。
#拷贝文件到远程主机,并指定属主为test用户 ansible ftp -m copy -a 'src=/root/hello dest=/opt owner=test'
group:此参数指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错
#拷贝文件到远程主机,并指定属主为test用户,所属组为test用户基本组 ansible ftp -m copy -a 'src=/root/hello dest=/opt owner=test group=test'
mode:此参数指定文件拷贝到远程主机后的权限,如果你想将权限设置为”rw-r–r–“,则可以使用mode=0644表示
#拷贝文件到远程主机,并指定属主为ftp用户,所属组为ftp用户基本组,并指定权限为0744 ansible ftp -m copy -a 'src=/root/hello dest=/opt owner=test group=test mode=0744'
第二十二章:Ansible剧本Playbook
在ansible中,类似”脚本”的文件被称作”剧本”,英文名称为’playbook’ ,用于配置,部署,和管理被控节点
我们只需要把模块按照顺序编排在playbook剧本中,ansible就会按照剧本一步一步的执行,最终达到我们的目的
YAML的语法特点
-
严格区分大小写
-
使用缩进表示层级关系
-
低版本缩进不允许使用tab键,只允许使用空格,缩进的空格数量没有严格要求,只要相同层级左对齐即可
-
#
号表示注释 -
书写YAML切记 : 后边要加一个空格
-
如果需要将多段YAML配置放在同一个文件中,中间需要用 — 作为分格
YAML常用数据结构
-
对象(Object):键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
-
数组:一组按次序排列的值,又称为序列(sequence) / 列表 (list)
对象类型:对象的一组键值对,使用冒号结构表示
#对象形式一(推荐)
个人信息:
name: zhangsan
age: 30
address: tianjin
#对象形式二(了解)
个人信息: {name: zhangsan,age: 30,address: tianjin}
数组类型:一组连词线开头的行,构成一个数组
- 联系方式:
phone: 138****6789
QQ:
WeChat:
emal:
复合结构:对象和数组可以结合使用,形成复合结构
个人信息:
name: zhangsan
age: 30
address: tianjin
- 联系方式:
phone:
QQ:
WeChat:
emal:
---
个人信息:
name: lisi
age: 30
address: tianjin
- 联系方式:
phone:
QQ:
WeChat:
emal:
playbook核心属性
- hosts:执行的远程主机列表
- remote_user: 指定远程操作时,使用的用户身份
- tasks:任务集
- name: 指定任务名称(名称自定义,在一个任务集中,任务可以有多个)
- variables:内置变量或自定义变量在playbook中调用
- tempaltes 模板,可替换文件中的变量并实现一些简单逻辑的文件
- handles 和notify结合使用,由特定条件触发的操作,满足条件方执行,否则不执行
- tags标签,指定某条任务执行,用于选择运行playbook中的部分代码。
编写第一个Playbook剧本
#使用ping模块测试远程主机联通性,并在远程主机创建目录
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’命令
ansible-playbook ping_websrvs.yml
Playbook源码部署Nginx的Web服务
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名称
ansible-playbook --syntax-check nginx.yml
playbook: nginx.yml
#--check 用于模拟执行playbook
ansible-playbook --check nginx.yml
#使用playbook剧本批量在远程主机源码安装nginx
ansible-playbook nginx.yml
Ansible学习文档:https://www.zsythink.net/archives/tag/ansible/page/5
常用软件地址
阿里云:http://mirrors.aliyun.com
搜狐:http://mirrors.sohu.com
163:http://mirrors.163.com
清华大学开源镜像站:https://mirrors.tuna.tsinghua.edu.cn/
阿里开源镜像站:https://developer.aliyun.com/mirror/
Redis官网:http://www.redis.cn/
CentOS官网:http://centos.org
宝塔官网https://www.bt.cn/
github:https://github.com/account/unverified-email
Docker Hub官方镜像仓库:https://hub.docker.com/
网易云容器镜像仓库:https://c.163yun.com/hub#/home
阿里云容器镜像仓库:https://cr.console.aliyun.com/cn-beijing/instances/images?accounttraceid=97b7ef46194040e8bb22e1fdbbb9a100ptqk
nginx官网:http://nginx.org/
zabbix官网:https://www.zabbix.com/
MySQL官网:https://www.mysql.com/
红帽官网:http://www.redhat.com/docs
slideshare官网(需翻墙):http://www.slideshare.net/ 提供某些技术点的PPT
grafana官网:https://grafana.com/
SQLyog(MySQL数据库客户端管理工具): https://www.webyog.com/
php地址:www.php.net
``
group:此参数指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错
#拷贝文件到远程主机,并指定属主为test用户,所属组为test用户基本组
ansible ftp -m copy -a 'src=/root/hello dest=/opt owner=test group=test'
mode:此参数指定文件拷贝到远程主机后的权限,如果你想将权限设置为”rw-r–r–“,则可以使用mode=0644表示
#拷贝文件到远程主机,并指定属主为ftp用户,所属组为ftp用户基本组,并指定权限为0744
ansible ftp -m copy -a 'src=/root/hello dest=/opt owner=test group=test mode=0744'
第二十二章:Ansible剧本Playbook
在ansible中,类似”脚本”的文件被称作”剧本”,英文名称为’playbook’ ,用于配置,部署,和管理被控节点
我们只需要把模块按照顺序编排在playbook剧本中,ansible就会按照剧本一步一步的执行,最终达到我们的目的
YAML的语法特点
-
严格区分大小写
-
使用缩进表示层级关系
-
低版本缩进不允许使用tab键,只允许使用空格,缩进的空格数量没有严格要求,只要相同层级左对齐即可
-
#
号表示注释 -
书写YAML切记 : 后边要加一个空格
-
如果需要将多段YAML配置放在同一个文件中,中间需要用 — 作为分格
YAML常用数据结构
-
对象(Object):键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
-
数组:一组按次序排列的值,又称为序列(sequence) / 列表 (list)
对象类型:对象的一组键值对,使用冒号结构表示
#对象形式一(推荐)
个人信息:
name: zhangsan
age: 30
address: tianjin
#对象形式二(了解)
个人信息: {name: zhangsan,age: 30,address: tianjin}
数组类型:一组连词线开头的行,构成一个数组
- 联系方式:
phone: 138****6789
QQ:
WeChat:
emal:
复合结构:对象和数组可以结合使用,形成复合结构
个人信息:
name: zhangsan
age: 30
address: tianjin
- 联系方式:
phone:
QQ:
WeChat:
emal:
---
个人信息:
name: lisi
age: 30
address: tianjin
- 联系方式:
phone:
QQ:
WeChat:
emal:
playbook核心属性
- hosts:执行的远程主机列表
- remote_user: 指定远程操作时,使用的用户身份
- tasks:任务集
- name: 指定任务名称(名称自定义,在一个任务集中,任务可以有多个)
- variables:内置变量或自定义变量在playbook中调用
- tempaltes 模板,可替换文件中的变量并实现一些简单逻辑的文件
- handles 和notify结合使用,由特定条件触发的操作,满足条件方执行,否则不执行
- tags标签,指定某条任务执行,用于选择运行playbook中的部分代码。
编写第一个Playbook剧本
#使用ping模块测试远程主机联通性,并在远程主机创建目录
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’命令
ansible-playbook ping_websrvs.yml
Playbook源码部署Nginx的Web服务
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名称
ansible-playbook --syntax-check nginx.yml
playbook: nginx.yml
#--check 用于模拟执行playbook
ansible-playbook --check nginx.yml
#使用playbook剧本批量在远程主机源码安装nginx
ansible-playbook nginx.yml
Ansible学习文档:https://www.zsythink.net/archives/tag/ansible/page/5
常用软件地址
阿里云:http://mirrors.aliyun.com
搜狐:http://mirrors.sohu.com
163:http://mirrors.163.com
清华大学开源镜像站:https://mirrors.tuna.tsinghua.edu.cn/
阿里开源镜像站:https://developer.aliyun.com/mirror/
Redis官网:http://www.redis.cn/
CentOS官网:http://centos.org
宝塔官网https://www.bt.cn/
github:https://github.com/account/unverified-email
Docker Hub官方镜像仓库:https://hub.docker.com/
网易云容器镜像仓库:https://c.163yun.com/hub#/home
阿里云容器镜像仓库:https://cr.console.aliyun.com/cn-beijing/instances/images?accounttraceid=97b7ef46194040e8bb22e1fdbbb9a100ptqk
nginx官网:http://nginx.org/
zabbix官网:https://www.zabbix.com/
MySQL官网:https://www.mysql.com/
红帽官网:http://www.redhat.com/docs
slideshare官网(需翻墙):http://www.slideshare.net/ 提供某些技术点的PPT
grafana官网:https://grafana.com/
SQLyog(MySQL数据库客户端管理工具): https://www.webyog.com/
php地址:www.php.net