"require_once(): Failed opening required" 但文件存在且可读

"require_once(): Failed opening required" but file exists and is readable

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

PHP Fatal error: require_once(): Failed opening required 'MailError.php' (include_path='.:/usr/www/users/web1/master/sys/classes:..') in [...]

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

在我的spl_autoload_register方法中调用了require_once

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,一个Node.js脚本,监听UDP套接字,Redis作为搜索结果缓存。我关闭了所有这些组件,现在看起来 Cronjob 是 运行,没有任何错误。后来我一个接一个地打开组件,看看是哪个导致了错误,但看起来只有每个组件都打开才会出现。

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

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

正如我在这个帖子中发现的那样 Select() + UDP resulting in too many open files 这个错误是打开文件限制越界的结果。

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