1. inotify
1.1. Inotify概述
Inotify 一种强大的、细粒度的、异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性、读写属性、权限属性、删除创建、移动等操作,也就是可以监控文件发生的一切变化。。
inotify-tools 是一个C库和一组命令行的工作提供Linux下inotify的简单接口。
inotify-tools安装后会得到inotifywait
和inotifywatch
这两条命令:
- inotifywait命令 用来收集有关文件访问信息
- inotifywatch命令 用于收集关于被监视的文件系统的统计数据,包括每个 inotify 事件发生多少次。
开始之前需要检测系统内核是否支持inotify:
使用uname -r
命令检查Linux内核,如果低于2.6.13,就需要重新编译内核加入inotify的支持。
[root@m01 ~]# uname -r
3.10.0-1160.el7.x86_64
使用ll /proc/sys/fs/inotify
命令,是否有以下三条信息输出,如果没有表示不支持。
[root@m01 ~]# ll /proc/sys/fs/inotify
total 0
-rw-r--r-- 1 root root 0 Sep 3 19:44 max_queued_events
-rw-r--r-- 1 root root 0 Sep 3 19:44 max_user_instances
-rw-r--r-- 1 root root 0 Sep 3 19:44 max_user_watches
1.2. 安装inotify-tools
-
inotify-tools项目地址:GitHub - inotify-tools/inotify-tools: inotify-tools is a C library and a set of command-line programs providing a simple interface to inotify.
-
inotify-tools下载地址:http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
tar zxvf inotify-tools-3.14.tar.gz
cd inotify-tools-3.14
./configure
make
make install
1.3. 修改inotify相关参数
/proc/sys/fs/inotify/下面的几个参数可以用来限制inotify消耗kernel memory的大小。
由于这些参数都是内存参数,因此,可以根据应用需求,实时的调节其大小:
max_queued_evnets
表示调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,
超出这个值的事件被丢弃,但会触发IN_Q_OVERFLOW事件。
max_user_instances
表示每一个real user id可创建的inotify instatnces的数量上限。
max_user_watches
表示每个inotify instatnces可监控的最大目录数量。如果监控的文件数目巨大,
需要根据情况,适当增加此值的大小。
#调整inotify内核参数
cat <<EOF> /etc/sysctl.conf
fs.inotify.max_queued_events=99999999
fs.inotify.max_user_instances = 1024
fs.inotify.max_user_watches=1048576
EOF
sysctl -p
1.4. inotifywait命令使用
inotifywait命令参数
● -m 是要持续监视变化。
● -r 使用递归形式监视目录。
● -q 减少冗余信息,只打印出需要的信息。
● -e 指定要监视的事件列表。
● --timefmt 是指定时间的输出格式。
● --format 指定文件变化的详细信息。
可监听的事件
access 访问 ,读取文件。
modify 修改 ,文件内容被修改。
attrib 属性 ,文件元数据被修改。
move 移动 ,对文件进行移动操作。
create 创建 ,生成新文件
open 打开 ,对文件进行打开操作。
close 关闭 ,对文件进行关闭操作。
delete 删除 ,文件被删除。
案例:监控/tmp/目录下,-e指定的事件,并按照--format指定的格式输出
[root@m01 ~]# inotifywait -mrq --timefmt '%y%m%d-/%H:%M:%S' --format '%T %w %f %e' -e modify,delete,create,attrib /tmp
240903-/20:53:52 /tmp/ 12.txt ATTRIB
240903-/20:54:12 /tmp/ 13.txt CREATE
240903-/20:54:12 /tmp/ 13.txt ATTRIB
240903-/20:54:32 /tmp/ .12.txt.swp CREATE
240903-/20:54:32 /tmp/ .12.txt.swx CREATE
240903-/20:54:32 /tmp/ .12.txt.swx DELETE
240903-/20:54:32 /tmp/ .12.txt.swp DELETE
240903-/20:54:32 /tmp/ .12.txt.swp CREATE
240903-/20:54:32 /tmp/ .12.txt.swp MODIFY
240903-/20:54:32 /tmp/ .12.txt.swp ATTRIB
240903-/20:54:33 /tmp/ .12.txt.swp MODIFY
240903-/20:54:42 /tmp/ .12.txt.swp MODIFY
1.5. inotifywatch命令使用
命令的作用是收集被监视的文件系统的统计数据,统计文件系统访问的次数, 包括每个inotify事件发生多少次。
inotifywatch以标准输出方式输出一个表,每种类型的事件为一列,每个监视的文件或目录为一行。 该表显示的是每个被监视的文件或目录中事件发生的次数。 可以使用-a或-d参数对特定事件对输出进行排序。
-a<event> 按指定事件计数的升序排序输出
--d<event> 按指定事件计数的降序排序输出
-fromfile<file> 从文件中读取需要监控的文件或排除的文件
-z 输出表格的行和列,即使元素为空
-r 监视一个目录下的所有子目录
-t 设置超时时间
-e<event> 只监听指定的事件
-- -exclude <pattern> 不处理文件名与指定的POSIX扩展,区分大小写
-- -excludei <pattern> 不处理文件名与指定的POSIX扩展,不区分大小写
案例:开始统计20秒内针对/tmp发生的一切事件,可以加-e指定事件
[root@m01 ~]# inotifywatch -t 20 -r /tmp
Establishing watches...
Finished establishing watches, now collecting statistics.
total access modify attrib close_write close_nowrite open create delete filename
26 2 4 1 4 3 7 3 2 /tmp/
案例:开始统计20秒内针对/tmp发生的一切事件,并以表格形式输出,最后一列为目录或文件
[root@m01 ~]# inotifywatch -t 20 -r /tmp -z
Establishing watches...
Finished establishing watches, now collecting statistics.
total access modify attrib close_write close_nowrite open moved_from moved_to move_self create delete delete_self filename
9 0 2 1 2 1 3 0 0 0 0 0 0 /tmp/
0 0 0 0 0 0 0 0 0 0 0 0 0 /tmp/.X11-unix/
0 0 0 0 0 0 0 0 0 0 0 0 0 /tmp/.Test-unix/
0 0 0 0 0 0 0 0 0 0 0 0 0 /tmp/.ICE-unix/
0 0 0 0 0 0 0 0 0 0 0 0 0 /tmp/.font-unix/
0 0 0 0 0 0 0 0 0 0 0 0 0 /tmp/.XIM-unix/
0 0 0 0 0 0 0 0 0 0 0 0 0 /tmp/vmware-root_847-4013198920/
2. rsync
2.1. rsync概述
rsync是一个快速和非常方便的文件复制工具。 它能本地复制,远程复制,或者远程守护进程方式复制
2.2. rsync安装
rpm -q rsync || yum install rsync -y
2.3. rsync命令的基本用法
本地使用: rsync [OPTION...] SRC... [DEST]
-----------------------------------------------------------
shell方式使用:
Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
-----------------------------------------------------------
通过服务方式使用:
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
指定rsync地址的两种方法
方式1-两个冒号分割形式: 用户名@主机地址::共享模块名
方式2-URL地址形式 :rsync://用户名@主机地址/共享模块名
-----------------------------------------------------------
Options:
-v, --verbose 详细模式输出
-q, --quiet 精简输出模式
-c, --checksum 打开校验开关,强制对文件传输进行校验
-a, --archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD
-r, --recursive 对子目录以递归模式处理
-p, --perms 保持文件权限
-l, --links 选项用来备份链接文件
-H,--hard-links 保留硬链接
-o, --owner 保持文件属主信息
-g, --group 保持文件属组信息
-z, --compress 对备份的文件在传输时进行压缩处理
-e 可选指定shell程序来连接远端服务器, 这样就可以加参数如
-e '-p 22' 指定端口
-e '-o StrictHostKeyChecking=no' 不检查hostkey,不再提示是否要连接
-A 保留ACL属性信息
-delete 删除那些DST中SRC没有的文件,保证两边文件同步对齐
2.3.1. 本地使用
本地使用: rsync [OPTION...] SRC... [DEST]
rsync -az /tmp1/ /mnt/
# 若/tmp 后边不加斜线,则会将tmp1目录给及目录内容拷贝过去
# 若/tmp/ 后边加了斜线,则会将tmp1目录下的内容给拷贝过去,而不会拷贝tmp1目录
2.3.2. shell方式使用
Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
#1 从远端拉取:以root用户连接10.0.0.12,把12的/home目录到本地/tmp目录下,本地/tmp目录下多了个home目录
rsync -avz -e 'ssh -p 22 -o StrictHostKeyChecking=no' root@10.0.0.12:/home /tmp
~]# ls /tmp/
home
#2 向远端推送:以root用户连接10.0.0.12,把本地/home目录到12的/tmp目录下,12的/tmp目录下多了个home目录
rsync -avz /home root@10.0.0.12:/tmp
#10.0.0.12查看/tmp/目录
[root@m2 ~]# ls /tmp/
home
2.3.3. 守护进程方式使用:
以守护进程运行rsync服务,客户端连接服务端进行推送
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
2.3.3.1. 配置rsync服务
#10.0.0.12机器作为服务端,这里需要修改hosts allow的ip地址段为你自己的
cat <<EOF> /etc/rsyncd.conf
#用户 远端的命令使用rsync访问共享目录
uid = rsync
#用户组
gid = rsync
#指定端口号,默认 873
port = 873
#允许非root用户在备份目录中创建文件或目录
fake super = yes
#安全相关,目前了解即可
use chroot = no
#最大连接数
max connections = 200
#超时时间
timeout = 300
#进程对应的进程号文件
pid file = /var/run/rsyncd.pid
#锁文件
lock file = /var/run/rsync.lock
#日志文件 出错
log file = /var/log/rsyncd.log
#忽略错误
#ignore errors
#可写
read only = false
#不能列表
list = false
#允许哪些机器可以连
hosts allow = 10.0.0.0/24
#拒绝哪些机器连
#host deny = 0.0.0.0/32
#虚拟用户,独立于系统用户之外的虚拟用户
auth users = rsync_backup
#虚拟账号里面对应的用户和密码
secrets file = /etc/rsync.password
#同步时不再压缩的文件类型,因为同步时,-avz已经进行压缩
dont compress = *.gz *.bz2 *.tgz *.zip *.rar *.z
#模块名称为config,外部用config连接
[config]
comment= config use
#服务器提供访问的目录
path = /data/backup/config/
#模块名称为data,外部用data连接
[data]
comment= data use
path = /data/backup/data/
EOF
#手动创建所需要的用户和目录文件
useradd rsync -s /sbin/nologin -M
mkdir -p /data/backup/{config,data}
chown rsync.rsync -R /data/backup/
#创建虚拟账号文件
cat <<EOF > /etc/rsync.password
rsync_backup:123456
EOF
chmod 600 /etc/rsync.password
systemctl restart rsyncd
2.3.3.2. 配置客户端
#10.0.0.11 作为客户端
#创建连接rsync服务端的密码
cat <<EOF > /etc/rsync.password
123456
EOF
chmod 600 /etc/rsync.password
#创建一个目录用于备份
mkdir -p /test/data{01..10}
#10.0.0.11客户端测试,把本地 /test/目录下的文件推送到备份服务器上的data模块中
#使用冒号分割方式推送
rsync -avz /test/ rsync_backup@10.0.0.12::data --password-file=/etc/rsync.password
#或者使用URL地址形式推送
#rsync -avz /test/ rsync://rsync_backup@10.0.0.12/data --password-file=/etc/rsync.password
2.3.3.3. 服务端验证
#10.0.0.12服务端验证,发现刚才的推送已经成功了
[root@m2 etc]# ls /data/backup/data/
data01 data02 data03 data04 data05 data06 data07 data08 data09 data10
3. inotofy+rsync实时同步方案
客户端使用脚本
cat <<'EOF'> /server/scripts/inotify.sh
#!/bin/bash
#要同步的目录列表
SRC_LIST=(
"/tmp/test1"
"/tmp/test2"
"/tmp/test3"
"/tmp/test4"
"/tmp/test5"
)
SERVERIP="10.0.0.12"
USER="rsync_backup"
PASSFILE="/etc/rsync.password"
MODULE_NAME="data"
for SRC in ${SRC_LIST[@]}
do
INOTIFY_CMD="inotifywait -mrq -e create,delete,move,modify,attrib $SRC"
RSYNC_CMD="rsync -azH --delete --password-file=${PASSFILE} $SRC ${USER}@${SERVERIP}::${MODULE_NAME}"
#进行一次全量同步
$RSYNC_CMD &
#持续监控,实时同步
$INOTIFY_CMD | while read DIRECTORY EVENT FILE
do
$RSYNC_CMD
done &
done
EOF
chmod +x /server/scripts/inotify.sh
chmod +x /etc/rc.d/rc.local
#开机自启动
grep inotify.sh /etc/rc.d/rc.local || echo "nohup /bin/bash /server/scripts/inotify.sh &">> /etc/rc.d/rc.local
4. 定时备份
实时同步,也就是2边文件保持一致,但是如果由于人为的原因删除了重要文件,同步也就没有意义了,2边文件都丢失了,此时需要一个能够定时备份的功能,当检测的目录发生变化,则生成一个压缩包传输到备份服务器,以此进行备份
cat <<'EOF' > /server/scripts/backup.sh
#!/bin/bash
#要同步的目录或文件列表
SRC_LIST=(
"/root/test/"
"/etc/hosts"
)
SERVERIP="10.0.0.12"
USER="rsync_backup"
PASSFILE="/etc/rsync.password"
MODULE_NAME="data"
LOCALIP=`hostname -I|awk '{print $1}'`
#把目录或者文件拷贝到/opt/${LOCALIP}/下,
#每隔60秒检查2个文件夹是否有差异,
#有差异
#同步代码到/opt/10.0.0.11/下,
#把代码打包推送到远端
#无差异则不做任何操作
#拷贝源目录到对比目录
for SRC in ${SRC_LIST[@]}
do
#/tmp/test1变为_tmp_test1,用于文件名
STRING_SRC=`echo $SRC|sed 's#/#_#g'`
DIR=/opt/${LOCALIP}
DEST=${DIR}/${STRING_SRC}
[ ! -e $DEST ] && { mkdir -p $DIR; cp -r $SRC $DEST; }
done
#持续对比
while true
do
sleep 60
for SRC in ${SRC_LIST[@]}
do
STRING_SRC=`echo $SRC|sed 's#/#_#g'`
DEST=/opt/${LOCALIP}/${STRING_SRC}
TAR_DIR=/opt/tar
#用于判断文件夹是否有变化
lines=`rsync -avz --dry-run $SRC $DEST |awk '/^sending/,/^sent/'|wc -l`
echo "lines= $lines"
#大于3就代表有变化
if [ $lines -gt 3 ]; then
rsync -avz $SRC $DEST
time=`date +%Y%m%d-%H%M%S`
mkdir -p $TAR_DIR && cd $TAR_DIR
tarName=$LOCALIP${STRING_SRC}-${time}.tar.gz
tar -cvf ${tarName} $DEST
rsync -az --password-file=${PASSFILE} ${tarName} ${USER}@${SERVERIP}::${MODULE_NAME}
fi
done
done
EOF
chmod +x /server/scripts/backup.sh
chmod +x /etc/rc.d/rc.local
#开机自启动
grep backup.sh /etc/rc.d/rc.local || echo "nohup /server/scripts/backup.sh &" >> /etc/rc.d/rc.local