这种文件锁定方法可以接受吗?

2024-03-29 00:12:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我们有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小时之间。在


Tags: 文件方法from标记import程序movetime
3条回答

在我看来,如果你改变了数据结构,要完成一些简单的事情,你付出了太多的努力。现在您有一个包含任务列表的文件。在

不如把任务队列改为一个目录,其中每个挂起的任务都是一个文件?然后,这个过程就像从“Pending”目录中选择一个任务一样简单,将其移动到目录(比如“Running”),完成后,将任务文件移动到“Completed”目录。因为文件移动是原子操作,所以不会有争用条件(如果移动失败,意味着另一个工作人员刚刚抢占了它,所以选择下一个任务)。在

另外,检查进度就像在其中一个目录上发出ls一样简单

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

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的现代操作系统中的上述代码示例,但有可能我在转换过程中引入了错误-只是警告一下)

顺便说一下,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中实现这一点,可以执行以下操作:

^{2}$

如果您不跟踪您的move调用,看看它们是否成功,您将永远不知道您是否成为定时窗口的牺牲品。请记住,如果有什么地方出了问题,它会在最坏的情况下,。在

与其使用文件的内容作为标志,不如使用文件名本身?对于每个任务,将文件“task_waiting_to \u run”重命名为“task_running”为“task_complete”。如果从“task_waiting_to_run”重命名为“task_running”失败,则意味着另一个框首先到达那里。在

相关问题 更多 >