gpt4 book ai didi

PHP file_exists 有时会为 CIFS 共享上的文件返回 false

转载 作者:IT王子 更新时间:2023-10-29 01:19:29 25 4
gpt4 key购买 nike

我有一个来自安装在 Ubuntu 14.04.2 LTS(内核 3.13.0-61-generic)上的 Windows Server 2012 R2 的 CIFS 共享,就像这样

/etc/fstab

//10.1.2.3/Share /Share cifs credentials=/root/.smbcredentials/share_user,user=share_user,dirmode=0770,filemode=0660,uid=4000,gid=5000,forceuid,forcegid,noserverino,cache=none 0 0
gid=5000 对应于运行 PHP 进程的组 www-data

当我通过以 www-data 用户身份登录的控制台进行检查时,文件已正确挂载 - 它们是可读和可移动的(PHP 脚本使用的操作)。

PHP 脚本每天处理大约 50-70 000 个文件。这些文件是在主机 Windows 机器上创建的,一段时间后,运行在 Linux 机器上的 PHP 脚本会收到有关新文件的通知,检查文件是否存在 ( file_exists ),读取它并删除。通常一切正常,但有时(每天数百到 1-2 000 个)PHP 脚本会引发文件不存在的错误。绝不应该是这种情况,因为它只通知实际存在的文件。

当我手动检查那些报告为不存在的文件时,它们可以在 Ubuntu 机器上正确访问,并且在 PHP 脚本检查它们存在之前具有创建日期。

然后我手动触发 PHP 脚本以获取该文件,并且它毫无问题地被获取。

我已经尝试过的

有多个类似的问题,但我似乎已经用完了所有的建议:
  • 我在检查 clearstatcache()
  • 之前添加了 file_exists($f)
  • 文件和目录权限没问题(完全相同的文件稍后正确拾取)
  • 检查 file_exists($f) 的路径是绝对路径,没有特殊字符 - 文件路径总是格式 /Share/11/222/333.zip(带有各种数字)
  • 我使用了 noserverino 共享挂载参数
  • 我使用了 cache=none 共享挂载参数
  • /proc/fs/cifs/Stats/ 显示如下,但我不知道这里是否有任何可疑之处。有问题的份额是 2) \\10.1.2.3\Share
    Resources in use
    CIFS Session: 1
    Share (unique mount targets): 2
    SMB Request/Response Buffer: 1 Pool size: 5
    SMB Small Req/Resp Buffer: 1 Pool size: 30
    Operations (MIDs): 0

    6 session 2 share reconnects
    Total vfs operations: 133925492 maximum at one time: 11

    1) \\10.1.2.3\Share_Archive
    SMBs: 53824700 Oplocks breaks: 12
    Reads: 699 Bytes: 42507881
    Writes: 49175075 Bytes: 801182924574
    Flushes: 0
    Locks: 12 HardLinks: 0 Symlinks: 0
    Opens: 539845 Closes: 539844 Deletes: 156848
    Posix Opens: 0 Posix Mkdirs: 0
    Mkdirs: 133 Rmdirs: 0
    Renames: 0 T2 Renames 0
    FindFirst: 21 FNext 28 FClose 0
    2) \\10.1.2.3\Share
    SMBs: 50466376 Oplocks breaks: 1082284
    Reads: 39430299 Bytes: 2255596161939
    Writes: 2602 Bytes: 42507782
    Flushes: 0
    Locks: 1082284 HardLinks: 0 Symlinks: 0
    Opens: 2705841 Closes: 2705841 Deletes: 539832
    Posix Opens: 0 Posix Mkdirs: 0
    Mkdirs: 0 Rmdirs: 0
    Renames: 0 T2 Renames 0
    FindFirst: 227401 FNext 1422 FClose 0

    我认为我看到的一种模式是,只有在 PHP 脚本之前已经处理(读取和删除)相关文件时才会引发错误。有许多文件已经正确处理,然后稍后再次处理,但我从未见过第一次处理的文件出现错误。重新处理之间的时间从 1 天到大约 20 天不等。对于重新处理,只需在 Windows 主机上的相同路径下使用更新的内容重新创建文件。

    可能是什么问题?我怎样才能更好地调查?如何确定问题出在 PHP 还是 OS 端?

    更新

    我已将生成文件的软件移至以相同方式安装相同共享的 Ubuntu VM。该组件是用 Java 编码的。读/写文件时我没有看到任何问题。

    更新 - PHP 详细信息

    确切的 PHP 代码是:
    $strFile = zipPath($intApplicationNumber);

    clearstatcache();

    if(!file_exists($strFile)){
    return responseInternalError('ZIP file does not exist', $strFile);
    }
    intApplicationNumber 是一个请求参数(例如 12345678 ),它被 zipPath() 函数简单地转换为路径(例如 \Share\12\345\678.zip - 始终是完整路径)。

    脚本可以与不同的申请号同时调用,但不会与同一个申请号同时调用。

    如果脚本失败(返回 'ZIP file does not exist' 错误),它将在一分钟后再次调用。如果失败,它将被永久标记为失败。然后,通常一个多小时后,我可以使用在生产中完成的相同调用(GET 请求)手动调用脚本,并且它工作正常,找到文件并在响应中发送:
    public static function ResponseRaw($strFile){
    ob_end_clean();
    self::ReadFileChunked($strFile, false);
    exit;
    }

    protected static function ReadFileChunked($strFile, $blnReturnBytes=true) {
    $intChunkSize = 1048576; // 1M
    $strBuffer = '';
    $intCount = 0;
    $fh = fopen($strFile, 'rb');

    if($fh === false){
    return false;
    }

    while(!feof($fh)){
    $strBuffer = fread($fh, $intChunkSize);
    echo $strBuffer;
    if($blnReturnBytes){
    $intCount += strlen($strBuffer);
    }
    }

    $blnStatus = fclose($fh);

    if($blnReturnBytes && $blnStatus){
    return $intCount;
    }

    return $blnStatus;
    }

    客户端收到文件后,通知 PHP 服务器可以将文件移动到存档位置(通过 copy()unlink() )。那部分工作正常。

    STRACE 结果

    几天没有错误后,错误再次出现。我运行 strace 并报告
    access("/Share/11/222/333.zip", F_OK) = -1 ENOENT (No such file or directory)

    对于从命令行运行 ls /Share/11/222/333.zip 时确实存在的某些文件。因此问题出在操作系统层面,PHP 不应该受到指责。

    当主机上的磁盘负载增加(由于其他进程)时,错误开始出现,因此下面@ri​​syasin 的建议似乎最有可能 - 这是资源繁忙/超时的问题。

    我会尝试@miguel-svq 的建议,跳过存在性测试,然后立即使用 fopen() 并处理错误。我会看看它是否有任何改变。

    最佳答案

    您可以尝试使用 方向避免在此挂载上打开的文件上进行 inode 数据缓存的选项:

    //10.1.2.3/Share /Share cifs credentials=/root/.smbcredentials/share_user,user=share_user,dirmode=0770,filemode=0660,uid=4000,gid=5000,forceuid,forcegid,noserverino,cache=none,directio 0 0

    关于PHP file_exists 有时会为 CIFS 共享上的文件返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35479776/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com