rsync 与仍在写入的文件的行为?

Lou*_*eru 14 linux apache-http-server rsync cron ubuntu

如果 Apache 正在编写一个大文件并且在该文件上运行 rsync cron 作业,rsync 是否尝试复制该文件?

例子

  • Apache-1:有大文件正在写入/var/www.
  • Apache-2:Apache-1 的克隆。每五分钟让 cron 运行 rsync 以获取/var/www同步。

Gia*_*968 23

如果 Apache 正在将某种类型的文件写入一个地方并且尚未完成写入然后 rsync启动,rsync则将复制位于那里的任何内容。

这意味着如果 Apache 正在处理一个 5MB 的文件,只有 2MB 被写入并rsync启动,部分 2MB 文件将被复制。因此该文件在目标服务器上看起来像是“损坏”。

根据您使用的文件大小,您可以使用--inplacein 选项rsync执行以下操作:

当文件的数据需要更新时,此选项会更改 rsync 传输文件的方式:与创建文件的新副本并在完成后将其移动到位的默认方法不同,rsync 将更新的数据直接写入目标文件。

这样做的好处是,如果 5MB 文件在第一次运行时只复制了 2MB,下一次运行将增加 2MB 并继续复制文件,直到完整的 5MB 到位。

不利的是,它可能会造成这样一种情况,即有人在复制文件时访问 Web 服务器,然后他们会看到部分文件。在我看来rsync,它在缓存“不可见”文件然后立即将其移动到位的默认行为中效果最好。但--inplace适用于大文件和带宽限制可能阻碍从 Square 轻松复制大文件的情况。

也就是说你确实陈述了这一点;重点是我的:

每五分钟让 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
Run Code Online (Sandbox Code Playgroud)

这个想法是通用的核心——我所拥有的echo "Hello world!"——是你脚本的核心所在。其余部分基本上是基于mkdir. 这个概念的一个很好的解释是在这个答案中

如果目录尚不存在,则mkdir创建一个目录,如果存在,则设置退出代码。更重要的是,它在单个原子操作中完成所有这些,使其非常适合这种情况。

因此,就您的rsync流程而言,我建议echo您只需将命令更改为您的命令即可使用此脚本rsync。另外,将 更改LOCK_NAME为类似的内容RSYNC_PROCESS,然后您就可以开始了。

现在,使用rsync此脚本包装后,您可以将 cron 作业设置为每分钟运行一次,而不会出现两个或多个rsync进程争相执行相同操作的竞争情况风险。这将允许您提高速度或rsync更新,这不会消除传输部分文件的问题,但它有助于加快整个过程,因此可以在某个时候正确复制完整文件。

  • 感谢您指出运行多个 rsync 的可能性,没想到这一点。剧本听起来很棒。我只是想了解将负载平衡站点与 rsync 同步的问题,这似乎可以缓解它们。精彩的奖金。仍然觉得这可能是错误的方法......但让我们看看:) (2认同)
  • @路易斯,不客气!另外,如果您想根据即时文件更改保持文件夹同步,我强烈建议您考虑使用/调整“lsyncd”。它允许您拥有“热文件夹”,真正关注其中的活动,然后在发生更改时对这些文件采取行动。正如我的回答中所述,我经常使用“rsync”,但对于需要非 cron/更直接的操作形式的情况,我使用“lsyncd”。 (2认同)