【问题标题】:"require_once(): Failed opening required" but file exists and is readable“require_once():需要打开失败”但文件存在且可读
【发布时间】:2020-03-18 05:39:25
【问题描述】:

从前几天我的一个 Cronjobs 遇到了一个严重的问题。有时我会收到以下错误(每小时一次或两次):

PHP 致命错误:require_once():在 [...]

PHP打开失败的文件每次都会变化。此外,所需的文件肯定存在并且是可读的。当 Cronjob 处于活动状态但没有锁定的 *.php 文件时,我尝试使用 lsof | grep .php 查找任何锁定的文件。

require_once 在我的spl_autoload_register 方法中被调用:

spl_autoload_register(function($className){
    $filePath = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    $includePaths = explode(PATH_SEPARATOR, get_include_path());
    foreach($includePaths as $includePath){
        if(file_exists($includePath . DIRECTORY_SEPARATOR . $filePath)){
            require_once $filePath;
            return;
        }
    }
});

在第一次遇到问题之前,我在服务器上安装了一些新软件。 Node.js,用于进程监控的 PM2,一个侦听 UDP 套接字和 Redis 作为搜索结果缓存的 Node.js 脚本。我关闭了所有这些组件,现在看起来 Cronjob 再次运行而没有任何错误。后来我一个接一个地打开组件,检查是哪一个导致错误,但看起来只有在每个组件都打开时才会出现。

我不知道这个问题的核心是什么,所以我希望我能找到遇到相同或类似问题的人。

关于我的系统的一些有用信息:

  • 安装了 Debian 9 的托管服务器
  • Node.js 和 Redis 随 Linuxbrew 一起安装
  • PHP 7.3.11-cli
  • 没有使用防病毒软件

【问题讨论】:

    标签: php node.js redis locking pm2


    【解决方案1】:

    正如我在这个线程Select() + UDP resulting in too many open files 中发现的那样,这个错误是由于打开文件限制超出了限制。

    在我的例子中,一个 PHP 脚本使用带有 socket_create()socken_sendto() 的 UDP 套接字,并使用 socket_close() 关闭它。关闭可能会失败,并且套接字保持打开状态。在某些时候,打开文件的限制已超过,PHP 无法包含任何其他文件。

    【讨论】:

      猜你喜欢
      • 2014-06-12
      • 1970-01-01
      • 2014-10-21
      • 2016-07-06
      • 2017-07-19
      • 2011-08-04
      • 2014-05-09
      相关资源
      最近更新 更多