0基础linux运维教程 Rsync结合inotify实现数据实时同步

了解rsync的优缺点之后,就需要了解Rsync结合inotify实现数据如何实时同步,以下案例可以供童鞋们一起学习下

## 七 Rsync结合inotify实现数据实时同步

### 7.1 rsync+inotify介绍

rsync+crond:只能实现数据的间隔同步(最小也是分钟级别的同步),无法实现实时同步,如果要做异地镜像点,肯定是需要实时同步的。

在Linux kernel 2.6.13后提供了inotify文件系统监控机制。通过rsync+inotify组合可以实现实时同步,制作异地镜像站点,以便为异地备份做好准备工作

### 7.2 安装inotify-tools

inotify由inotify-tools包提供。在安装inotify-tools之前,请确保内核版本高于2.6.13,且在/proc/sys/fs/inotify目录下有以下三项,这表示系统支持inotify监控,关于这3项的意义,下文会简单解释。

```

[root@local ~]# ll /proc/sys/fs/inotify/

total 0

-rw-r--r-- 1 root root 0 Feb 11 19:57 max_queued_events

-rw-r--r-- 1 root root 0 Feb 11 19:57 max_user_instances

-rw-r--r-- 1 root root 0 Feb 11 19:57 max_user_watches

```

epel源上提供了inotify-tools工具,或者下载源码包格式进行编译。

inotify-tools源码包地址:

以下为编译安装过程:

```

tar xf inotify-tools-3.14.tar.gz

./configure --prefix=/usr/local/inotify-tools-3.14

make && make install

ln -s /usr/local/inotify-tools-3.14 /usr/local/inotify

```

inotify-tools工具只提供了两个命令。

```

[root@local ~]# rpm -ql inotify-tools | grep bin/

/usr/bin/inotifywait

/usr/bin/inotifywatch

```

其中inotifywait命令用于等待文件发生变化,所以可以可以实现监控(watch)的功能,该命令是inotify的核心命令。inotifywatch用于收集文件系统的统计数据,例如发生了多少次inotify事件,某文件被访问了多少次等等,一般用不上。

以下是inotify相关的内核参数。

> (1)./proc/sys/fs/inotify/max_queued_events:调用inotify_init时分配到inotify instance中可排队的event数的最大值,超出值时的事件被丢弃,但会触发队列溢出Q_OVERFLOW事件。

>

> (2)./proc/sys/fs/inotify/max_user_instances:每一个real user可创建的inotify instances数量的上限。

>

> (3)./proc/sys/fs/inotify/max_user_watches:每个inotify实例相关联的watches的上限,即每个inotify实例可监控的最大目录、文件数量。如果监控的文件数目巨大,需要根据情况适当增加此值。

如:

```bash

[root@xuexi ~]# echo 30000000 > /proc/sys/fs/inotify/max_user_watches

```

### 7.3 inotifywait命令与事件

#### 7.3.1 inotifywait命令

|   选项   |                       说明                       |

| :------: | :----------------------------------------------: |

|    -m    |                     持续监听                     |

|    -r    |               使用递归形式监视目录               |

|    -q    |         减少冗余信息,只打印出需要的信息         |

|    -e    |      指定要监视的事件,多个时间使用逗号隔开      |

| –timefmt |                     时间格式                     |

| –format  | 监听到的文件变化的信息,信息格式自定义,详解下表 |

–format 参数说明:

| 参数 |                             说明                             |

| :--: | :----------------------------------------------------------: |

|  %w  |                      表示发生事件的目录                      |

|  %f  |    表示发生事件的文件,%w%f组在一起即表发生事件的绝对路径    |

|  %e  | 表示发生的事件,事件默认是以逗号为分隔符的,例如CLOSE_WRITE,CLOSE |

| %Xe  | 事件以“X”分隔,例如CLOSE_WRITEXCLOSE,代表事件CLOSE_WRIT与CLOSE |

|  %T  |   使用由--timefmt定义的时间格式,此时必须指定--timefmt参数   |

-e指定的监控事件

```bash

create:在被监控的目录中创建了文件或目录

delete:删除了被监控目录中的某文件或目录

modify:修改,文件内容被修改

access:文件被访问

attrib:元数据被修改。包括权限、时间戳、扩展属性等等

close_write:打开的文件被关闭,是为了写文件而打开文件、随后被关闭的事件,比如用vim编辑文件或者echo 1111 >> egon.txt 

close_nowrite:read only模式下文件被关闭,即只能是为了读取而打开文件,读取结束后关闭文件的事件

close:是close_write和close_nowrite的结合,无论是何种方式打开文件,只要关闭都属于该事件

open:文件被打开

moved_to:向监控目录下移入了文件或目录,也可以是监控目录内部的移动

moved_from:将监控目录下文件或目录移动到其他地方,也可以是在监控目录内部的移动

move:是moved_to和moved_from的结合

moved_self:被监控的文件或目录发生了移动,移动结束后将不再监控此文件或目录

delete_self:被监控的文件或目录被删除,删除之后不再监控此文件或目录

umount:挂载在被监控目录上的文件系统被umount,umount后不再监控此目录

isdir :监控目录相关操作

```

#### 7.3.2 事件分析

监控目录

```bash

[root@egon ~]# mkdir /egon_bak

[root@egon ~]# inotifywait -m /egon_bak/ #在前台监控目录/egon_bak,未指定监控的事件,默认监控所有

Setting up watches.

Watches established.

```

打开另外一个终端,对被监控目录/egon_bak进行一些操作,来查看触发的事件

```bash

验证文件的增删改查,vim编辑文件,cp拷贝,mv移动文件等操作触发的事件

验证目录的增删改查,cp拷贝文件到目录下,mv移入移出等操作触发的事件

```

大致总结如下

```bash

# 文件的增删改

监控目录下新增了某个文件->触发的事件:

CREATE

MODIFY

CLOSE_WRITE,CLOSE

监控目录下的某个文件被删除->触发的事件

DELETE

监控目录下的某个文件内容被修改->触发的事件

MODIFY

CLOSE_WRITE,CLOSE

监控目录下的某个文件属性被修改->触发的事件

ATTRIB

监控目录下的某个文件被mv到别的目录中->出发的事件

MOVED_FROM

某个文件被mv到了监控目录或其子目录下->出发的事件

MOVED_TO

# 目录的增删改同上

CREATEXISDIR

DELETEXISDIR

ATTRIBXISDIR

MOVED_FROMXISDIR

MOVED_TOXISDIR

```

从上面的测试结果中可以发现,很多动作都涉及了close事件,且大多数情况都是伴随着close_write事件的。所以,大多数情况下在定义监控事件时,其实并不真的需要监控open、modify、close事件。特别是close,只需监控它的分支事件close_write和close_nowrite即可。由于一般情况下inotify都是为了监控文件的增删改,不会监控它的访问,所以一般只需监控close_write即可。

由于很多时候定义触发事件后的操作都是根据文件来判断的,例如a文件被监控到了变化(不管是什么变化),就立即执行操作A,又由于对文件的一个操作行为往往会触发多个事件,例如cat查看文件就触发了open、access、close_nowrite和close事件,这样很可能会因为多个事件被触发而重复执行操作A。

综合以上考虑,我们应该尽量做到监控对象减少重复,但这一点其实很难实现

```bash

inotifywait -mrq --timefmt '%Y-%m-%d %H:%M:%S' --format '%w%f:%Xe:%T' -e create,delete,modify,move,attrib,close_write /test

```

### 7.3.3 rsync+inotify脚本

该脚本需要运行在本地 ,并且需要远端开启rsyncd

```bash

#!/bin/bash


watch_dir=/test/               # 本地被监控目录

user="egon"                    # 虚拟用户

export RSYNC_PASSWORD=123      # 虚拟用户密码

module="xxx"                   # 远程模块名

ip=192.168.12.39               # 远程主机ip

# 先整体同步一次

rsync -azc --delete ${watch_dir} ${user}@${ip}::${module}

# 切换到被监控目录下,然后用inotifywait监控./目录,这样后期就可以用-R选项同步新增的子目录

cd $watch_dir  

/usr/bin/inotifywait -mrq --timefmt '%Y-%m-%d %H:%M:%S' --format '%w%f:%Xe:%T' -e create,delete,modify,move,attrib,close_write ./ \

--exclude=".*.swp" | \

while read line

do

    # $line的输出format为:文件路径:事件:时间

    FILE=$(echo $line | awk -F: '{print $1}')  # 获取文件的绝对路径

    EVENT=$(echo $line | awk -F: '{print $2}') # 获取监控的事件

    # 监控到对文件的下述行为后,只把文件同步到远端

    if [[ $EVENT =~ 'CREATE' ]] || [[ $EVENT =~ 'MODIFY' ]] || [[ $EVENT =~ 'CLOSE_WRITE' ]] || [[ $EVENT =~ 'MOVED_TO' ]] || [[ $EVENT =~ 'ATTRIB' ]];then

        rsync -azcR ${FILE} ${user}@${ip}::${module}

    fi


    # 监控到涉及到目录的改动,将目录同步到远端,例如用dirname ${FILE}获取目录

    if [[ $EVENT =~ 'DELETE' ]] || [[ $EVENT =~ 'MOVED_FROM' ]];then

        rsync -azcR --delete $(dirname ${FILE}) ${user}@${ip}::${module} &>/dev/null

    fi

done &

# 末尾的&符号,代表在子shell中提交命令,这样进程的ppid就变为1,当前窗口关闭,该进程依然存活

```

远程(配置好rsync守护进程,模块为xxx,虚拟用户名egon,密码123),执行下述命令检测同步情况

```bash

while true;do ls /egon_bak;sleep 0.5;clear;done

```

你可能感兴趣的:(0基础linux运维教程 Rsync结合inotify实现数据实时同步)