我在服务器上有一个文件results.txt
,可由多个VM通过NFS访问。一个进程在每个VM上运行,这些VM读取results.txt
文件并对其进行修改。如果两个进程A
和B
同时读取该文件,则根据进程写入的顺序,results.txt
中将出现对A或B的修改文件。
如果进程A
对文件有写锁定,那么进程B
必须等到释放锁才能读取results.txt
文件。
我尝试使用Python实现它:
import fcntl
f = open("/path/result.txt")
fcntl.flock(f,fcntl.LOCK_EX)
#code
它可以正常工作在本地磁盘上。
但是当我运行尝试锁定已安装路径上的文件时,我收到以下错误:
Traceback (most recent call last):
File "lock.py", line 12, in <module>
fcntl.flock(f,fcntl.LOCK_EX)
IOError: [Errno 45] Operation not supported
我尝试了fcntl.fcntl
和fcntl.flock
,但却遇到了同样的错误。这是我使用fcntl
的方式的问题吗?是否需要在存储文件的服务器上进行任何配置?
修改
这就是我使用fcntl.fcntl
的方式:
f= open("results.txt")
lockdata = struct.pack('hhllhh', fcntl.F_RDLCK,0,0,0,0,0)
rv = fcntl.fcntl(f, fcntl.F_SETLKW, lockdata)
NFS服务器版本为3。
答案 0 :(得分:3)
我发现flufl.lock最符合我的要求。
从项目page引用作者:
[...] O_EXCL在NFS文件系统上被破坏,这些程序依赖于 它 执行锁定任务将包含竞争条件。该 使用锁文件执行原子文件锁定的解决方案是 在相同的fs上创建一个唯一的文件(例如,合并主机名和 pid),使用link(2)建立到lockfile的链接。如果link()返回 0,锁定成功。否则,在唯一文件上使用stat(2) 检查其链接数是否增加到2,在这种情况下锁定 也很成功。
由于它不是标准库的一部分,我无法使用它。此外,我的要求只是该模块提供的所有功能的一部分。
以下功能是基于模块编写的。请根据要求进行更改。
def lockfile(target,link,timeout=300):
global lock_owner
poll_time=10
while timeout > 0:
try:
os.link(target,link)
print("Lock acquired")
lock_owner=True
break
except OSError as err:
if err.errno == errno.EEXIST:
print("Lock unavailable. Waiting for 10 seconds...")
time.sleep(poll_time)
timeout-=poll_time
else:
raise err
else:
print("Timed out waiting for the lock.")
def releaselock(link):
try:
if lock_owner:
os.unlink(link)
print("File unlocked")
except OSError:
print("Error:didn't possess lock.")
这是一个适用于我的粗略实现。我一直在使用它,并没有遇到任何问题。有很多事情可以改进。希望这可以帮助。