我在服务器上有一个文件results.txt
,多个虚拟机可以通过NFS访问该文件。每个虚拟机上都运行一个进程,该进程读取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。
我发现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.")
这是一个对我有用的粗糙实现。我一直在使用它,没有遇到任何问题。不过,还有很多地方可以改进。希望这能有所帮助。