Python中os.path.exists()在存在的NFS挂载目录文件失败

5

我基本上有一个网站的Web服务器和另一个简单存储文件的服务器。文件服务器通过装载其中一个目录连接到主服务器。该网站运行Django,因此我主要处理Python。无论如何,当实际存在文件时,我似乎遇到了一些文件不存在的问题。

实质上,当我调用

filepath = '/path/to/file/on/nfs/share'
exists = os.path.exists(filepath)

即使文件存在,但exists为false。我知道文件确实存在,因为我打印了时间戳到一个日志文件中,可以准确地显示它是何时创建的。我不确定问题可能出在哪里,但我知道os.path.exists文档上说:

在某些平台上,如果未被授予对所请求文件执行os.stat()的权限,则此函数可能返回False,即使该路径物理上存在。

我知道这不是问题所在,因为两个文件都共享相同的组和组号,这在两个服务器上也共享相同的组号。可能是过期缓存之类的问题吗?
我的挂载是通过fstab自动完成的。
Client side, the settings are:
filehost:/filefolder /localfolder nfs defaults,rsize=32768,wsize=32768

Server side, the settings are:
/filefolder webserver(rw,sync,no_root_squash,no_subtree_check)

编辑:

所以,我想要更多的信息/细节。我正在运行一个Python子进程,在远程目录中生成一个文件。当请求被发出时,它启动子进程并返回文件的预期位置。

在前端,有一个url被ping,它调用os.path.exists()来检查该文件是否存在,当存在时,资源就通过ajax加载。

疑似问题是有时这个pinger会报告文件在实际存在几秒钟后仍不可用。这也是我认为可能是过时缓存的可能问题的原因。

所有的文件和它们所在的目录都是所有者/组www-data,任何由django实例化的子进程也是如此。而且,这个问题似乎并不完全可重复。有时它会比预期快,而有时它会比预期慢几秒钟。


+1 是因为我很感兴趣。实际上,文件系统是本地挂载还是远程挂载对于 os.path 应该是透明的。一旦挂载完成,它应该表现出相同的行为。 - Hyperboreus
就我所知,我在一个nfs挂载的目录上进行了测试,并返回了true。也许可以在/path/、/path/to/、/path/to/file/等位置调用exists函数,看看它从哪里开始返回False? - Daniel Rucci
丹说了什么。还有,了解共享目录(以及其挂载点)的权限和所有权以及脚本运行的用户是谁也很重要。 - tink
2个回答

3
这是由于NFS缓存造成的,如此处所述:

属性缓存会缓存struct stat中的所有内容,因此stat()和fstat()调用可以从缓存中返回。如果您需要查看文件的最新大小或修改时间(或其他字段),则需要在stat()调用之前刷新文件的属性缓存。

请注意,如果文件句柄已缓存,则stat()返回该缓存文件的信息(因此结果与fstat()相同)。如果您需要使用给定的文件名stat()最新文件,请先刷新文件句柄缓存。

我认为这是因为文件尚未缓存在cache中导致了stat()失败。 我在NFS手册中找到了这个: ac / noac - 选择客户端是否可以缓存文件属性。 如果未指定任何选项(或指定了ac),则客户端会缓存文件属性。 但是那里也有一个警告,所以我只好忍受延迟:

使用noac选项可在访问相同文件的NFS客户端之间提供更大的缓存一致性,但会带来显著的性能损失。 因此,建议谨慎使用文件锁定。 数据和元数据一致性部分包含了这些权衡的详细讨论。


0

同样的错误! 加一行代码解决了我的问题。 可能是由于NFS缓存引起的。

dir_name = "/path/to/file/on/nfs/share"
# add this line
os.system(f"ls -l {dir_name}")
exists = os.path.exists(filepath)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接