跳转到主要内容

于 2025年04月22日 摘录自 Postfix and NFS

Postfix 对 NFS 的支持状态

Postfix 在 NFS 上的支持状态如何?答案是,当您使用 NFS 时,Postfix 本身是受支持的,但无法保证与 NFS 相关的问题会及时获得 Postfix 的解决方法,甚至无法保证解决方法是否可行。

不过,Postfix 在大多数情况下在 NFS 上运行良好,因为 Postfix 实现了多个解决方法(见下文)。良好的 NFS 实现很少会与 Postfix 出现问题,因此 Wietse 建议您明智地使用资源。

Postfix 文件锁定与 NFS

对于 Postfix 邮件队列而言,NFS 文件锁定机制的优劣并不重要。原因是无法在多个运行中的 Postfix 实例之间共享 Postfix 队列。您可以使用 NFS 将 Postfix 邮件队列从一个 NFS 客户端切换到另一个,但任何时刻仅有一个 NFS 客户端可以访问 Postfix 邮件队列。

对于使用 NFS 共享邮件箱文件,您的选项包括使用 fcntl(内核锁定)、dotlockusername.lock 文件)、同时使用两种锁定方法,或切换到 maildir 格式。maildir 格式为每封邮件使用一个文件,无需 Postfix 或其他邮件软件提供文件锁定支持。

许多使用邮箱格式的站点为了保险起见,同时使用两种锁定方法。

/etc/postfix/main.cf:
virtual_mailbox_lock = fcntl, dotlock
mailbox_delivery_lock = fcntl, dotlock

Postfix NFS 解决方法

下面的列表总结了截至2003年年中在NFS上运行Postfix时存在的解决方法。需要注意的是,Postfix本身在NFS上仍受支持,但不保证与NFS相关的问题会及时获得Postfix的解决方法,也不保证解决方法甚至可行。

  • 问题:重命名文件时,操作可能成功但仍报告错误[1]

    解决方法:当 rename(old, new) 报告错误时,Postfix 会检查新名称是否存在且旧名称已删除。如果检查成功,Postfix 假设 rename() 操作已正常完成。

  • 问题:创建目录时,操作可能成功但仍报告错误[1]

    解决方法:当 mkdir(new) 报告 EEXIST 错误时,Postfix 会检查新名称是否解析为目录。如果检查成功,Postfix 假设 mkdir() 操作正常完成。

  • 问题:创建文件的硬链接时,操作可能成功但仍报告错误[1]

    解决方法:当 link(old, new) 失败时,Postfix 会比较旧文件和新文件的设备号和 inode 号。如果两个文件相同,Postfix 假设 link() 操作已正常完成。

  • 问题:创建点锁文件(username.lock)时,操作可能成功但仍报告错误[1]

    解决方法:在此情况下,唯一安全的操作是稍后重试。

  • 问题:当文件服务器的"时间"时钟与客户端的"时间"时钟不同步时,邮件投递会延迟一分钟或更长时间。

    解决方法:Postfix 显式设置文件时间戳以避免新邮件投递延迟(Postfix 使用"最后修改"文件时间戳来决定队列文件是否已准备好投递)。

[1] 操作如何在成功执行后仍报告错误?

假设一个 NFS 服务器成功执行了客户端请求,但服务器对客户端的响应丢失了。过了一段时间,客户端重新向服务器发送请求。通常,服务器会记住它已经完成了该请求(它会保存最近完成的请求和响应的列表),并简单地重新发送响应。

然而,当服务器重新启动或非常繁忙时,服务器不再记得它已经完成了请求,并重复执行操作。这不会对文件读写请求造成问题(它们包含文件偏移量,因此可以安全地重复执行),但会导致非幂等操作失败。例如,当服务器执行一个重新传输的 rename() 请求时,服务器会报告 ENOENT 错误,因为旧名称不存在;当服务器执行一个重新传输的 link()、mkdir() 或 create() 请求时,服务器会报告 EEXIST 错误,因为名称已经存在。

因此,成功的、非幂等、NFS 操作在服务器响应丢失、客户端重传请求且服务器未记住已完成该请求时,会报告错误。