【问题标题】:python os.path.exists() failing for nfs mounted directory file that existspython os.path.exists() 对于存在的 nfs 挂载目录文件失败
【发布时间】:2014-02-13 01:37:49
【问题描述】:

我基本上有一个网站的网络服务器和一个简单地存储文件的网络服务器。文件服务器通过挂载其目录之一连接到主服务器。该网站运行 Django,所以我主要处理 python。无论如何,我似乎遇到了一些文件被报告为不存在的问题,即使它们实际上存在。

基本上在我打电话时

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

exists 是假的,即使该文件实际存在,我也知道它确实存在,因为我将时间戳打印到一个日志文件中,该日志文件准确地显示了它的创建时间。我不确定可能是什么问题,但我知道 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 子进程,它在远程目录中生成一个文件。发出请求时,它会启动子进程并返回文件的预期位置。

在前端,有一个被 ping 的 url,它为该文件调用 os.path.exists(),然后通过 ajax 加载资源。

怀疑的问题是,有时此 pinger 会在文件实际可用后的几秒钟内报告该文件不可用。这也是我认为陈旧缓存可能存在问题的原因。

其中的所有文件和目录都是所有者/组 www-data,以及由 django 实例化的任何子进程。此外,这个问题似乎并不完全可重复。有时它会很快工作,而另一些则需要比预期多几秒钟的时间

【问题讨论】:

  • +1 因为我很感兴趣。实际上,文件系统是本地安装还是远程安装对os.path 应该是透明的。安装后,它的行为应该相同。
  • FWIW,我在 nfs 挂载目录上进行了测试,结果返回 true。也许调用存在于 /path/、/path/to/、/path/to/file/ 等以查看它从哪里开始返回 False?
  • 丹说了什么。最好知道共享目录(及其挂载点)上的权限和所有权是什么,以及您以什么用户身份运行脚本。

标签: python linux django ubuntu-12.04 nfs


【解决方案1】:

这是由于找到了 here 的 NFS 缓存:

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

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

我认为它的stat 失败是因为文件尚未在缓存中。 我在 NFS 手册页中找到了这个:

ac / noac - Selects whether the client may cache file attributes. If neither option is specified (or if ac is specified), the client caches file attributes.

但是那里也有一个警告,所以我只是忍受延迟:

使用 noac 选项可在访问相同文件的 NFS 客户端之间提供更高的缓存一致性,但会导致显着的性能损失。因此,鼓励明智地使用文件锁定。数据和元数据一致性部分包含对这些权衡的详细讨论。

【讨论】:

    【解决方案2】:

    同样的错误! 添加一行解决我的问题。 可能是因为 nfs 缓存

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-20
      • 2010-09-07
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      相关资源
      最近更新 更多