python - 这种文件锁定方法是否可以接受?

标签 python linux networking locking

我们有 10 个 Linux 机器,每周必须运行 100 个不同的任务。当我们在家时,这些计算机主要在晚上执行这些任务。我的一位同事正在从事一个项目,通过使用 Python 自动启动任务来优化运行时间。他的程序将读取任务列表,抓取一个打开的任务,在文件中将该任务标记为正在进行中,然后一旦任务完成,就在文件中将任务标记为完成。任务文件将在我们的网络挂载上。

我们意识到不建议让一个程序的多个实例访问同一个文件,但我们真的看不到任何其他选择。当他在寻找一种防止两台计算机同时写入文件的方法时,我想出了一个自己的方法,这个方法似乎比我们在网上找到的方法更容易实现。我的方法是检查文件是否存在,如果不存在则等待几秒钟,如果存在则暂时移动文件。我写了一个脚本来测试这个方法:

#!/usr/bin/env python

import time, os, shutil
from shutil import move
from os import path


fh = "testfile"
fhtemp = "testfiletemp"


while os.path.exists(fh) == False:
    time.sleep(3)

move(fh, fhtemp)
f = open(fhtemp, 'w')
line = raw_input("type something: ")
print "writing to file"
f.write(line)
raw_input("hit enter to close file.")
f.close()
move(fhtemp, fh)

在我们的测试中,这种方法奏效了,但我想知道我们是否会遇到一些使用这种方法没有发现的问题。我意识到两台计算机同时运行 exists() 可能会导致灾难。两台计算机不太可能同时到达那个点,因为任务在 20 分钟到 8 小时之间。

最佳答案

您基本上已经开发了二进制信号量(或互斥量)的文件系统版本。它是一个经过充分研究的用于锁定的结构,因此只要您获得正确的实现细节,它就应该可以工作。诀窍是让“测试和设置”操作,或者在你的情况下“检查存在和移动”,成为真正的原子。为此,我会使用这样的东西:

lock_acquired = False
while not lock_acquired:
    try:
        move(fh, fhtemp)
    except:
        sleep(3)
    else:
        lock_acquired = True
# do your writing
move(fhtemp, fh)
lock_acquired = False

您所拥有的程序大部分时间都可以运行,但如前所述,如果另一个进程在检查文件是否存在和调用 move 之间移动文件,您可能会遇到问题。我想你可以解决这个问题,但我个人建议坚持使用经过良好测试的互斥算法。 (我已经从 Andrew Tanenbaum 的 Modern Operating Systems 翻译/移植了上面的代码示例,但是我可能在转换中引入了错误 - 只是公平警告)

顺便说一下,Linux 上open 函数的手册页提供了这种文件锁定解决方案:

The solution for performing atomic file locking using a lockfile is to create a unique file on the same file system (e.g., incorporating hostname and pid), use link(2) to make a link to the lockfile. If link() returns 0, the lock is successful. Otherwise, use stat(2) on the unique file to check if its link count has increased to 2, in which case the lock is also successful.

要在 Python 中实现它,您可以这样做:

# each instance of the process should have a different filename here
process_lockfile = '/path/to/hostname.pid.lock'
# all processes should have the same filename here
global_lockfile = '/path/to/lockfile'
# create the file if necessary (only once, at the beginning of each process)
with open(process_lockfile, 'w') as f:
    f.write('\n') # or maybe write the hostname and pid

# now, each time you have to lock the file:
lock_acquired = False
while not lock_acquired:
    try:
        link(process_lockfile, global_lockfile)
    except:
        lock_acquired = (stat(process_lockfile).st_nlinks == 2)
    else:
        lock_acquired = True
# do your writing
unlink(global_lockfile)
lock_acquired = False

关于python - 这种文件锁定方法是否可以接受?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3322011/

相关文章:

python - 无法从Notebook中的Javascript调用Python函数

linux - 如何使用cp linux将同名文件从多个目录复制到新目录

linux - 如何停止读取剥离空间

networking - GStreamer:通过网络传输 vorbis 编码的音频

windows - 为什么需要 IP_MULTICAST_IF 和 IPV6_MULTICAST_IF?

python - Twisted如何读取/etc/hosts?

python - Python 中有 FileIO 吗?

python - time.sleep() 不暂停视频中的计时器

c - 缓冲区未正确读取字符串

java - 如何从网络发送数据到linux服务器