执行此操作的常用方法是使用 flock utility,它是 util-linux 软件包的一部分。 FreeBSD 和 NetBSD 软件包也可用,aiui,可能还有其他软件包。 (对于 MacOSX,请参阅this question。)
flock 命令既可以执行读取(“共享”)锁,也可以执行写入(“独占”)锁。它基于flock(2) 系统调用,因此是合作锁定(也称为咨询锁定),但在大多数应用程序中都可以正常工作(但请参阅下面文件的情况远程)。
上面链接的手册页中有使用示例。最简单的用例是
flock /tmp/lockfile /usr/local/bin/do_the_update
flock /tmp/lockfile -s /usr/local/bin/do_the_rsync
两者都获得了/tmp/lockfile的锁,然后执行指定的命令(大概是一个shell脚本)。第一条命令获得排他锁;我可以使用-x 选项明确说明这一点。第二条命令获取共享锁。
由于问题实际上涉及网络锁的需要,有必要指出flock() 在网络文件系统上可能不可靠。通常,目标文件应该始终是本地文件。
即使在非分布式应用程序中,您也需要考虑失败的可能性。例如,假设您在本地进行 rsync 以创建副本。如果主机在 rsync 正在进行时崩溃,您将得到一个不完整或损坏的副本。 rsync 可以从中恢复,但不能确定当主机重新启动时,rsync 会在文件被修改之前启动。这应该不是问题,但您绝对需要考虑到这一点。
在分布式应用程序中,情况更为复杂,因为整个系统很少出现故障。您可以有不同服务器或网络本身的独立故障。
建议锁定不是持久的。如果 lockfile 的主机在持有锁的情况下崩溃并重新启动,则重新启动后将不会持有锁。另一方面,如果持有锁的远程服务器之一崩溃并重新启动,它可能不知道它正在持有锁,在这种情况下,锁将永远不会被释放。
如果两台服务器都 100% 了解彼此的状态,这不是问题,但很难区分网络故障和主机故障。
您需要评估风险。与本地情况一样,如果文件服务器在 rsync 进行时崩溃,它可能会重新启动并立即开始修改文件。如果文件服务器关闭时远程 rsync 没有失败,它们将继续尝试同步,并且生成的副本将损坏。使用 rsync,这应该会在下一个同步周期自行解决,但在此期间您会遇到问题。您需要确定这有多严重。
您可以通过使用持久锁来防止文件服务器在启动时启动 mutator。每个 rsync 服务器在启动 rsync 之前在主机上创建自己的锁文件(并且在知道文件存在之前不会启动 rsync)并在释放读取锁之前删除文件。如果一个rsync服务器重启并且它的indicator文件存在,它就知道在rysnc期间发生了crash,所以它必须删除indicator文件并重启rsync。
这大部分在大多数情况下都可以正常工作,但如果 rsync 服务器在 rsync 期间崩溃并且永远不会重新启动,或者仅在很长一段时间后才重新启动,则它可能会失败。 (或者,等效地,如果网络故障使 rsync 服务器隔离了很长时间。)在这些情况下,很可能需要手动干预。在文件服务器上运行一个看门狗进程会很有用,它会在读锁持有时间过长时向操作员发出警报,对于“过长”的某些定义。