制作一致的maildir副本

Joj*_*GME 8 backup maildir data-consistency

假设我正在使用 Dovecot 并且它是 maildir 格式来保存和访问服务器上的邮件。复制maildir时如何避免竞争条件?


我确实阅读了一些关于备份和使用 maildir 的教程,但没有看到有人写过这个。他们只是使用cprsync将目录复制到另一个地方。maildir 不可能通过复制变成不一致的状态还是我需要某种锁定?

编辑:我想进行定期备份,但我认为这并不适合这个问题。我知道我可以停止邮件服务器(Dovecot 和 Postfix),但我认为不这样做应该是可能的。据我所知,maildir 支持不同应用程序的并发访问。

Joj*_*GME 9

我只是阅读了 Dovecot 中 Maildir 的文档以及一些关于 Maildir 和 Maildir++ 的其他文档。我希望我没有错过任何重要的事情。


Maildir 旨在无锁工作。大多数必需的操作在现代文件系统上都是原子的。这意味着您不必太在意诸如不一致读取之类的竞争条件。但是如果您想在邮件服务器运行时备份 Maildir,仍然存在一些问题。

问题

  • 备份和恢复tmp/是没有用的。每个 Maildir 包含目录new/,cur/tmp/. 目录tmp/包含正在写入磁盘的邮件。new/写入成功后将移至。这意味着文件中的文件tmp/可能尚未完成。即使文件完整,在恢复备份后,写入文件的进程也不再运行。这意味着,如果此类文件被还原,则永远不会将其添加到邮箱中,也可能永远不会被删除。

  • dovecot-uidlist.lock从备份中排除可能是明智的。Dovecot 使用名为 Maildir++ 的 Maildir 扩展。这个扩展需要锁定。扩展不需要获取读取锁,但从备份中排除锁文件可能是明智的。

  • 获取dovecot-uidlist.lock或使用文件系统的快照。基本上,您可以只复制目录,但可能会因竞争条件而错过一些邮件。原因是列出和复制目录的内容(递归)不是原子的。这意味着当用户更改标签(例如看到/未看到)或移动邮件时,在创建备份时可能会错过电子邮件。为了处理这种情况,Dovecot 为每个动作获取锁文件(同上)。如果您使用的是 Dovecot,则可以通过在创建备份之前获取锁来解决问题。这可以通过/usr/lib/dovecot/maildirlock. 另一种可能性是使用文件系统的快照。由于创建快照是原子的,因此问题不会出现在快照上。

作为一个快速总结:如果您想在 Dovecot 运行时进行备份,您应该首先获取锁定文件dovecot-uidlist.lock或创建文件系统的快照。然后,您可以复制Maildir。从您的备份中排除tmp/和排除可能是明智的dovecot-uidlist.lock


小智 6

这个问题的更新答案是使用 dovecot 的 doveadm 或 dsync 命令。例子:

dsync -f -u <user> backup maildir:<backup_location>
Run Code Online (Sandbox Code Playgroud)

有一个dovecot-backup shell 脚本,它添加了一些很好的环绕 dsync 来循环遍历所有用户邮箱、压缩文件、修剪旧备份并在发生错误时发送电子邮件警报。