Centos 6.5 rsync+inotify 两台服务器文件实时同步
rsync和inotify是什么我这里就不在介绍了,有专门的文章介绍这两个工具。
1. 两台服务器IP地址分别为:
源服务器:192.168.1.2
目标服务器:192.168.1.3
@todo:从源服务器(192.168.1.2)的/www/目录下的所有的文件实时同步到目标服务器(192.168.1.3)的/www_bak/目录下
源服务器下需要安装rsync和inotify,源服务器做为server端,实时的向目标服务器client端发送数据
2. 安装 rsync
一般centos6.5下都已经安装了rsync,所以就不必安装了,可以用以下命令检查一下是否已安装:
rpm -qa |grep rsync
上图显示了我的机器上安装的是rsync-3.0.6-12。
如果没有安装请往下看,如果已安装,那就跳过下面的部分:
cd /usr/local/src
wget http://rsync.samba.org/ftp/rsync/src/rsync-3.0.9.tar.gz
tar zxvf rsync-3.0.9.tar.gz
cd rsync-3.0.9
./configure --prefix=/usr/local/rsync
make
make install
rsync已安装完毕
3. 创建同步文件所需要的密码文件,这样做是为了安全
touch /etc/rsyncd.secrets
echo 'newpassword' > /etc/rsyncd.secrets
注:这里的newpassword可以是任意字符
出于安全考虑要把此文件的权限改成600:
chmod 600 /etc/rsyncd.secrets
4. 安装inotify
先查看服务器是否支持inotify
ll /proc/sys/fs/inotify
会有三个文件,这说明此服务器是支持 inotify的。
下面安装inotify:
wget http://cloud.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 --prefix=/usr/local/inotify
make
make install
5. 创建rsync复制脚本,用户shell来实现,其功能就是:从源服务器(192.168.1.2)的/www/目录下的所有的文件无论是添加、修改、删除文件,能够通过inotify监控到,并通过rsync实时同步到目标服务器(192.168.1.3)的/www_bak/目录下
vim /usr/bin/rsync.sh
#!/bin/bash
host=192.168.1.3
src=/www/
des=web
user=webuser
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src
| while read files
do
/usr/bin/rsync -zrtopg --delete --progress --password-file=/etc/rsyncd.secrets $src $user@$host::$des
echo "${files} was rsynced" > /var/log/rsyncd.log 2>&1
done
其中host是目标服务器的ip,src是源服务器要同步的目录,des是认证模块名,需要与目标服务器一致,user是建立密码文件里的认证用户。
修改rsync.sh的权限
chmod +x /usr/bin/rsync.sh
到此为止,源服务器的所有操作就完成了。
下面配置目标服务器:
-
目标服务器也要安装 rsync,安装方式跟源服务器一样,这里就不在赘述了。
-
建立密码文件:
touch /etc/rsyncd.secrets echo "webuser:newpassword" > /etc/rsyncd.secrets
同样要给此文件一个600的权限
chmod 600 /etc/rsyncd.secrets
注:在源服务器建立的密码文件,只有密码,没有用户名;而在目标服务器里建立的密码文件,用户名与密码都有。
-
写rsync的配置文件:
vim /etc/rsyncd.conf
uid = root gid = root use chroot = no max connections = 10 strict modes = yes pid file = /var/run/rsyncd.pid lock file = /var/run/rsync.lock log file = /var/log/rsyncd.log #log format = %t %a %m %f %b # 日志记录格式 [web] path = /www_bak/ comment = web file ignore errors read only = no write only = no hosts allow = 192.168.1.2 hosts deny = * list = false uid = root gid = root auth users = webuser secrets file = /etc/rsyncd.secrets
-
目标服务器启动 rsync
/usr/bin/rsync --daemon --config=/etc/rsyncd.conf
-
源服务器启动同步:
/usr/bin/rsync.sh &
到这里,所有的都已完成。可以到源服务器下的/www目录下建一个文件,然后再看一下目标服务器下的/www_bak/下是否有.
注意事项和改进建议
-
日志记录问题
-
当前脚本中,日志文件的内容会被覆盖,因为使用了
>
操作符。建议改为>>
,以便追加内容:echo "${files} was rsynced" >> /mnt/rsync/rsyncd.log 2>&1
-
-
rsync 的效率问题
- 每次检测到事件时,脚本会同步整个目录,而不是只同步发生变化的文件。这可能导致不必要的网络流量和性能开销。可以考虑使用
rsync
的--include
和--exclude
选项,或者结合inotifywait
的事件信息,只同步发生变化的文件。
- 每次检测到事件时,脚本会同步整个目录,而不是只同步发生变化的文件。这可能导致不必要的网络流量和性能开销。可以考虑使用
-
密码文件的安全性
- 密码文件
/mnt/rsync/rsyncd.secrets
需要确保只有脚本运行者有权限访问,避免泄露密码。
- 密码文件
-
错误处理
-
当前脚本没有对
rsync
的执行结果进行检查。建议添加错误处理逻辑,例如:if ! rsync -zrtopg --delete --progress --password-file=/mnt/rsync/rsyncd.secrets $src $user@$host::$des; then echo "Rsync failed for ${files}" >> /mnt/rsync/rsyncd.log 2>&1 else echo "${files} was rsynced" >> /mnt/rsync/rsyncd.log 2>&1 fi
-
-
并发问题
- 如果多个事件同时触发,可能会导致多个
rsync
进程同时运行,影响性能。可以考虑使用队列机制来处理事件。
- 如果多个事件同时触发,可能会导致多个
改进后的脚本示例:
#!/bin/bash
host=192.168.10.9
src=/mnt/disk0/zfox/
des=web
user=webuser
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src | while read files
do
if ! rsync -zrtopg --delete --progress --password-file=/mnt/rsync/rsyncd.secrets $src $user@$host::$des; then
echo "Rsync failed for ${files}" >> /mnt/rsync/rsyncd.log 2>&1
else
echo "${files} was rsynced" >> /mnt/rsync/rsyncd.log 2>&1
fi
done
排除监控与同步*.log的文件
#!/bin/bash
host=192.168.10.9
src=/mnt/disk0/zfox/
des=web
user=webuser
# 使用 inotifywait 的 --exclude 参数排除 *.log 文件
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib --exclude '\.log$' $src | while read files
do
# 使用 rsync 的 --exclude 参数排除 *.log 文件
if ! rsync -zrtopg --delete --progress --password-file=/mnt/rsync/rsyncd.secrets --exclude '*.log' $src $user@$host::$des; then
echo "Rsync failed for ${files}" >> /mnt/rsync/rsyncd.log 2>&1
else
echo "${files} was rsynced" >> /mnt/rsync/rsyncd.log 2>&1
fi
done
注意事项
- 如果目录中频繁发生大量变化(如批量文件操作),可能会导致多个
rsync
进程同时运行,从而增加系统负载和网络流量。在这种情况下,可以考虑以下优化:- 限制同步频率:通过
sleep
延迟同步操作,避免过于频繁地触发同步。 - 队列机制:将事件信息存储到队列中,按顺序处理,避免并发同步。
- 仅同步变化的文件:结合
inotifywait
提供的文件路径信息,仅同步发生变化的文件,而不是整个目录。
- 限制同步频率:通过
为了优化脚本并引入队列机制,可以使用一个简单的文件队列来存储事件信息,并通过一个单独的同步进程按顺序处理队列中的事件。这样可以避免并发同步带来的性能问题。以下是优化后的脚本实现:
优化思路
- 事件队列:使用一个文件作为事件队列,将
inotifywait
捕获到的事件信息写入队列文件。 - 同步进程:启动一个单独的同步进程,从队列文件中读取事件信息,并按顺序执行同步操作。
- 去重机制:为了避免重复同步相同的文件或目录,可以对队列中的事件进行去重处理。
优化后的脚本
1. 创建事件队列文件
创建一个队列文件用于存储事件信息:
touch /mnt/rsync/event_queue.log
2. 修改监控脚本
将事件信息写入队列文件,而不是直接触发同步:
#!/bin/bash
host=192.168.10.9
src=/mnt/disk0/zfox/
queue_file=/mnt/rsync/event_queue.log
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e modify,delete,create,attrib $src | while read event
do
echo "$event" >> "$queue_file"
done
3. 创建同步进程脚本
从队列文件中读取事件信息,并按顺序执行同步操作:
#!/bin/bash
host=192.168.10.9
src=/mnt/disk0/zfox/
des=web
user=webuser
queue_file=/mnt/rsync/event_queue.log
log_file=/mnt/rsync/rsyncd.log
password_file=/mnt/rsync/rsyncd.secrets
# 创建一个临时文件用于存储去重后的事件
temp_file=$(mktemp)
# 持续监控队列文件
while true; do
# 读取队列文件内容并去重
sort -u "$queue_file" > "$temp_file"
mv "$temp_file" "$queue_file"
# 检查队列文件是否为空
if [[ -s "$queue_file" ]]; then
# 读取队列文件中的第一个事件
IFS= read -r event < "$queue_file"
# 删除队列文件中的第一个事件
sed -i '1d' "$queue_file"
# 执行同步操作
if ! rsync -zrtopg --delete --progress --password-file="$password_file" "$src" "$user@$host::$des"; then
echo "Rsync failed for $event" >> "$log_file"
else
echo "$event was rsynced" >> "$log_file"
fi
fi
# 稍作延迟,避免过于频繁地检查队列文件
sleep 1
done
优化后的脚本工作流程
- 监控脚本:
- 使用
inotifywait
监控目录/mnt/disk0/zfox/
。 - 将捕获到的事件信息写入队列文件
/mnt/rsync/event_queue.log
。
- 使用
- 同步进程脚本:
- 持续监控队列文件
/mnt/rsync/event_queue.log
。 - 从队列文件中读取事件信息,并按顺序执行同步操作。
- 使用
sort -u
对队列文件中的事件进行去重处理,避免重复同步。 - 每次处理完一个事件后,从队列文件中删除该事件。
- 持续监控队列文件
优点
- 避免并发同步:通过队列机制,确保每次只处理一个事件,避免多个
rsync
进程同时运行。 - 去重处理:避免对同一个文件或目录进行重复同步,提高效率。
- 灵活性:可以根据需要调整同步的频率(通过
sleep
参数)。
启动脚本
-
启动监控脚本:
nohup ./monitor_script.sh &
-
启动同步进程脚本:
nohup ./sync_process.sh &
注意事项
- 确保队列文件和日志文件的路径正确,并且有足够的权限访问。
- 如果队列文件中积压了大量事件,可以适当调整
sleep
的时间,以加快处理速度。 - 在生产环境中,建议对同步进程脚本进行适当的错误处理和日志记录,以便更好地监控和调试。
通过这种方式,你可以有效地优化脚本,避免并发同步带来的问题,并提高同步操作的效率和可靠性。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。