如何实现lockfile命令的功能

How to implement the functionality of lockfile command

我正在尝试为在集群上运行的软件实现基于文件系统的锁。底层共享文件系统是使用DRBD实现的,所以可以认为同步性是有保证的。我当前的实现如下所示:

# check the lock file                                                                                                 
if os.path.isfile(lockfile):                                                                                       
    if time.time() - os.path.getmtime(lockfile) > 3600:                                                             
        logInfo('lock is older than 3600s, removing it and going on collecting result.')                           
        os.remove(lockfile)                                                                                        
    else:                                                                                                             
        logInfo('Previous action is still on-going, please wait until it\'s finished or timeout.')
        sys.exit(1)

# create the lock file                                                                                                
open(lockfile, 'w').close();

显然,集群中不同机器上的多个脚本实例 运行 可能会一致认为系统已解锁,创建锁定文件并执行需要互斥的操作。

所以总结起来,我需要一个基于文件系统的锁定工具,锁检查和创建一起形成一个原子操作。

可以使用 lockfile 命令在 shell 脚本中实现相同的功能。

一个解决方案可以通过使用os.open来实现,它包装了open系统调用:

import os,errno
def lockfile(filename):
    try:
        os.close(os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY));
    except OSError as e:
        if e.errno == errno.EEXIST:  # System is already locked as the file already exists.
            return False
        else:  # Something unexpected went wrong so reraise the exception.
            raise
    return True  # System has successfully been locked by the function

注意 os.open() 的第二个参数。根据 this answer,当结合 O_CREAT 使用标志 O_EXCL 并且路径名已经存在时,open() 将失败,或者更准确地说,将引发 OSError with errno EEXIST,在我们的例子中意味着系统已经被锁定。然而,当路径指向一个不存在的文件时,它会立即被创建,不会为文件系统的其他用户同时执行相同的步骤留下时间范围。 并且根据 this one,所描述的技术可以被认为是广泛的平台无关的。