如果 Apache 正在写入一个大文件,并且 rsync cron 作业在该文件上运行,rsync 是否会尝试复制该文件?
例子
- Apache-1:正在将较大的文件写入
/var/www
。 - Apache-2:Apache-1 的克隆。每五分钟 cron 运行 rsync 以同步
/var/www
。
答案1
如果 Apache 正在将某种文件写入某个位置但尚未完成写入进而 rsync
开始执行,rsync
将复制那里的任何内容。
这意味着如果 Apache 正在处理一个 5MB 的文件,则只有 2MB 被写入并rsync
启动,部分 2MB 文件将被复制。因此该文件在目标服务器上看起来就像是“损坏”的。
根据您使用的文件的大小,您可以使用选项--inplace
执行rsync
以下操作:
当文件数据需要更新时,此选项会更改 rsync 传输文件的方式:rsync 不会采用默认方法,即创建文件的新副本并在完成后将其移动到位,而是将更新的数据直接写入目标文件。
这样做的好处是,如果 5MB 文件在第一次运行时仅复制了 2MB,则下一次运行将从 2MB 开始继续复制文件,直到复制满 5MB。
缺点是,它可能会导致有人在复制文件时访问 Web 服务器,然后他们会看到部分文件。在我看来,rsync
它默认的行为效果最好,即缓存“不可见”文件,然后立即将其移动到位。但--inplace
对于大文件和带宽限制可能阻碍从头开始轻松复制大文件的情况,它很有用。
这就是说,你确实这么说过;重点是我的:
每五分钟有 cron 运行 rsync…
所以我假设您已经准备好一些 bash 脚本来管理这个 cron 作业?嗯,这个脚本rsync
足够智能,只复制需要复制的文件。如果您有一个每 5 分钟运行一次的脚本,那么rsync
当脚本运行得更快时,您似乎在试图避免互相干扰。这意味着,如果您每分钟运行一次,则存在一个或多个进程由于文件大小或网络速度而仍在运行的风险rsync
,而下一个进程将与之竞争;这是一种竞争状态。
避免这种情况的一种方法是将整个rsync
命令包装在检查文件锁的 bash 脚本中;下面是我用于此类情况的样板 bash 脚本框架。
请注意,有些人会建议使用flock
,但由于flock
在我使用的某些系统上没有安装 - 而且我经常在 Ubuntu(有它)和 Mac OS X(没有)之间切换 - 我使用这个简单的框架没有任何实际问题:
LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'
if mkdir ${LOCK_DIR} 2>/dev/null; then
# If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
echo $$ > ${PID_FILE}
echo "Hello world!"
rm -rf ${LOCK_DIR}
exit
else
if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
# Confirm that the process file exists & a process
# with that PID is truly running.
echo "Running [PID "$(cat ${PID_FILE})"]" >&2
exit
else
# If the process is not running, yet there is a PID file--like in the case
# of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
rm -rf ${LOCK_DIR}
exit
fi
fi
这个想法是,通用核心(我所指的echo "Hello world!"
)是脚本的核心所在。其余部分基本上是基于的锁定机制/逻辑mkdir
。对概念的一个很好的解释在这个答案中:
建立目录如果目录尚不存在,则创建目录;如果目录存在,则设置退出代码。更重要的是,它在一个原子操作中完成所有这些操作,非常适合此场景。
因此,对于您的rsync
流程,我建议您使用此脚本,只需将命令更改echo
为您的rsync
命令即可。此外,将 更改LOCK_NAME
为类似 的内容RSYNC_PROCESS
,然后您就可以开始了。
现在,使用rsync
此脚本,您可以将 cron 作业设置为每分钟运行一次,而不会出现两个或多个rsync
进程争相执行相同操作的竞争情况。这将允许您提高速度或rsync
更新,虽然这不会消除部分文件传输的问题,但它将有助于加快整个过程,以便可以在某个时候正确复制整个文件。
答案2
是的 - 如果 rsync 在写入文件的同时读取该文件,则该文件可能已损坏。
您可以尝试以下操作: https://unix.stackexchange.com/a/2558
您也可以使用 lsof 编写脚本:
lsof /path/to file
退出代码为 0 表示文件正在使用中,退出代码为 1 表示该文件没有活动。