Python:在NFS上锁定文本文件



我在服务器上有一个文件results.txt,多个虚拟机可以通过NFS访问该文件。每个虚拟机上都运行一个进程,该进程读取results.txt文件并对其进行修改。如果两个进程AB同时读取文件,则根据进程写入文件的顺序,在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.fcntlfcntl.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。

我发现flufl.lock最适合我的需求。

引用项目页面的作者:

[…]O_EXCL在NFS文件系统上损坏,程序依赖它用于执行锁定任务的将包含竞争条件。这个使用lockfile执行原子文件锁定的解决方案是在相同的fs上创建一个唯一的文件(例如,合并hostname和pid),使用链接(2)创建到锁定文件的链接。如果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.")

这是一个对我有用的粗糙实现。我一直在使用它,没有遇到任何问题。不过,还有很多地方可以改进。希望这能有所帮助。

最新更新