inotify + rsync 实时同步 ,定时备份

1. inotify

1.1. Inotify概述

Inotify 一种强大的、细粒度的、异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性、读写属性、权限属性、删除创建、移动等操作,也就是可以监控文件发生的一切变化。。

inotify-tools 是一个C库和一组命令行的工作提供Linux下inotify的简单接口。

inotify-tools安装后会得到inotifywaitinotifywatch这两条命令:

  • 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

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
相关推荐
PieroPc7 分钟前
Python 自动化 打开网站 填表登陆 例子
运维·python·自动化
Aileen_0v011 分钟前
【AI驱动的数据结构:包装类的艺术与科学】
linux·数据结构·人工智能·笔记·网络协议·tcp/ip·whisper
州周1 小时前
Ftp目录整个下载
linux·服务器·数据库
Jackey_Song_Odd1 小时前
Ubuntu 24.04.1 解决部分中文字符(门、径)显示错误的问题
linux·ubuntu
kaixin_learn_qt_ing1 小时前
Linux export命令
linux
余额不足121381 小时前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
冷曦_sole1 小时前
linux-19 根文件系统(一)
linux·运维·服务器
AI大模型学徒1 小时前
Linux(二)_清理空间
linux·运维·服务器
云川之下1 小时前
【linux】 unshare -user -r /bin/bash命令详解
linux·bash·unshare
tntlbb2 小时前
Ubuntu20.4 VPN+Docker代理配置
运维·ubuntu·docker·容器