2015-10-16 23 views
2

我正在实现基于文件锁定的互斥机制。我的脚本的其他实例知道,当它们碰到一个锁定的特定文件时,它们不应该运行。如何在没有竞争条件的情况下删除锁定的(flock)文件:释放锁之前还是之后?

为了达到这个目的,我使用fcntl.flock创建并锁定了文件。当我释放锁时,我也想清理文件,当没有进程正在运行时,它不会坐在那里指示一个旧的pid。

我的问题是,何时以及如何清理文件,特别是在什么时候可以删除它。基本上,我看到两个选项:

  • 截断并删除文件上的锁被释放
  • 截断之前,并删除文件上的锁被释放

后,从我的理解,每一个暴露我的应用程序到略有不同的比赛条件。什么是最佳实践,我错过了什么?

下面是一个(过分简化的)例子:

import fcntl 
import os 
import sys 
import time 

# open file for read/write, create if necessary 
with open('my_lock_file.pid', 'a+') as f: 
    # acquire lock, raises exception if lock is hold by another process 
    try: 
     fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB) 
    except IOError: 
     print 'other process running:', f.readline() 
     sys.exit() 

    try: 
     # do something 
     f.write('%d\n' % os.getpid()) 
     f.flush() 
     # more stuff here ... 
     time.sleep(5) 
    finally: 
     # clean up here? 
     # release lock 
     fcntl.flock(f, fcntl.LOCK_UN) 
     # clean up here? 
# clean up here? 
+1

也非常相关的信息:HTTP:// stacko verflow.com/q/17708885/1025391 – moooeeeep

回答

1

我发现此相关的问题提供有关如何处理这种情况的一些建议:

它还让我意识到另一个可能的竞争条件,这是在另一个进程刚刚被cur打开后删除文件时发生的租赁过程。 这会导致当前进程锁定一个不再在文件系统中找到的文件,从而无法阻止下一个会重新创建它的进程。

在那里,我发现建议使用开放标记O_EXCL进行原子排他性文件创建,这是通过os.open()函数公开的低级文件操作。 我然后相应地采取了以下例子:

import os 
import sys 
import time 

# acquire: open file for write, create if possible, exclusive access guaranteed 
fname = 'my_lock_file.pid' 
try: 
    fd = os.open(fname, os.O_CREAT|os.O_WRONLY|os.O_EXCL) 
except OSError: 
    # failed to open, another process is running 
    with open(fname) as f: 
     print "other process running:", f.readline() 
     sys.exit() 

try: 
    os.write(fd, '%d\n' % os.getpid()) 
    os.fsync(fd) 
    # do something 
    time.sleep(5) 
finally: 
    os.close(fd) 
    # release: delete file 
    os.remove(fname) 

实施在此之后,我发现这是完全一样的方法的lockfile模块使用其PID文件。

参考:

+0

如果脚本在“执行某些操作”步骤中异常退出,锁定文件将不会被删除。所有将来运行该脚本的尝试都将打印“其他进程正在运行”消息,因为如果该文件已存在,“os.O_EXCL”会导致发生错误。由于这个原因,像[fasteners](http://fasteners.readthedocs.io/en/latest/api/process_lock.html)包中提供的进程锁等其他方法不会清理锁文件。如果您想允许删除锁定文件,我认为您需要在获取锁定后对文件进行统计,如链接到的答案中所述。 –

相关问题