PHP - 无法打开流 : No such file or directory

标签 php require fopen include-path

在PHP脚本中,是否调用include() , require() , fopen() ,或其派生词,例如 include_once , require_once ,甚至,move_uploaded_file() ,经常会遇到错误或警告:

Failed to open stream : No such file or directory.



什么是快速找到问题根本原因的好过程?

最佳答案

可能会遇到此错误的原因有很多,因此,一份关于首先要检查的内容的良好 list 有很大帮助。

让我们考虑我们正在对以下行进行故障排除:

require "/path/to/file"

list

1.检查文件路径是否有拼写错误
  • 要么手动检查(通过目视检查路径)
  • 或移动由 require* 调用的任何内容或 include*到它自己的变量,回显它,复制它,然后尝试从终​​端访问它:
    $path = "/path/to/file";
    
    echo "Path : $path";
    
    require "$path";
    

    然后,在终端中:
    cat <file path pasted>
    


  • 2.检查文件路径是否正确关于相对与绝对路径的考虑
  • 如果它以正斜杠“/”开头,那么它不是指您网站文件夹的根目录(文档根目录),而是指您服务器的根目录。
  • 例如,您网站的目录可能是 /users/tony/htdocs
  • 如果它不是以正斜杠开头,那么它要么依赖于包含路径(见下文),要么路径是相对的。如果是相对的,那么PHP会相对于current working directory的路径进行计算。 .
  • 因此,与您网站根目录的路径或您键入的文件无关
  • 因此,请始终使用绝对文件路径

  • 最佳实践:

    为了使您的脚本在您四处移动时保持稳健,同时在运行时仍生成绝对路径,您有 2 个选项:
  • 使用 require __DIR__ . "/relative/path/from/current/file" . __DIR__ magic constant返回当前文件的目录。
  • 定义一个 SITE_ROOT不断地自己:
  • 在您网站目录的根目录下,创建一个文件,例如config.php
  • config.php ,写
    define('SITE_ROOT', __DIR__);
    
  • 在要引用站点根文件夹的每个文件中,包含 config.php ,然后使用 SITE_ROOT随心所欲:
    require_once __DIR__."/../config.php";
    ...
    require_once SITE_ROOT."/other/file.php";
    

  • 这 2 种做法还使您的应用程序更具可移植性,因为它不依赖于包含路径之类的 ini 设置。

    3. 检查你的包含路径

    包含文件的另一种方法(既不是相对也不是绝对绝对)是依赖 include path .库或框架(例如 Zend 框架)通常就是这种情况。

    这样的包含看起来像这样:
    include "Zend/Mail/Protocol/Imap.php"
    

    在这种情况下,您需要确保“Zend”所在的文件夹是包含路径的一部分。

    您可以使用以下命令检查包含路径:
    echo get_include_path();
    

    您可以使用以下命令向其中添加文件夹:
    set_include_path(get_include_path().":"."/path/to/new/folder");
    

    4. 检查您的服务器是否有权访问该文件

    总的来说,运行服务器进程(Apache 或 PHP)的用户根本没有读取或写入该文件的权限。

    要检查服务器在哪个用户下运行,您可以使用 posix_getpwuid :
    $user = posix_getpwuid(posix_geteuid());
    
    var_dump($user);
    

    要找出文件的权限,请在终端中键入以下命令:
    ls -l <path/to/file>
    

    并查看 permission symbolic notation

    5.检查PHP设置

    如果以上都不起作用,那么问题可能是某些 PHP 设置禁止它访问该文件。

    三个设置可能相关:
  • open_basedir
  • 如果设置了这个,PHP 将无法访问指定目录之外的任何文件(甚至不能通过符号链接(symbolic link))。
  • 但是,默认行为是不设置它,在这种情况下没有限制
  • 这可以通过拨打 phpinfo() 来检查。或使用 ini_get("open_basedir")
  • 您可以通过编辑 php.ini 文件或 httpd.conf 文件来更改设置
  • safe mode
  • 如果启用此功能,则可能会应用限制。但是,这已在 PHP 5.4 中删除。如果您仍然使用支持安全模式升级到 PHP 版本的版本 still being supported .
  • allow_url_fopen and allow_url_include
  • 这仅适用于通过网络进程(例如 http://)包含或打开文件,而不适用于尝试包含本地文件系统上的文件
  • 这可以通过 ini_get("allow_url_include") 检查并设置为 ini_set("allow_url_include", "1")


  • 角箱

    如果以上都无法诊断问题,以下是可能发生的一些特殊情况:

    1.依赖包含路径的包含库

    您可能会使用相对或绝对路径包含一个库,例如 Zend 框架。例如:
    require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
    

    但是你仍然会遇到同样的错误。

    这可能是因为您(成功)包含的文件本身具有另一个文件的包含语句,并且第二个包含语句假定您已将该库的路径添加到包含路径。

    例如,前面提到的 Zend 框架文件可能包含以下内容:
    include "Zend/Mail/Protocol/Exception.php" 
    

    这既不是相对路径的包含,也不是绝对路径的包含。假设 Zend 框架目录已添加到包含路径中。

    在这种情况下,唯一实用的解决方案是将目录添加到包含路径中。

    2.SELinux

    如果您运行的是 Security-Enhanced Linux,则可能是由于拒绝从服务器访问文件而导致问题的原因。

    查看是否启用了 SELinux 在您的系统上,运行 sestatus终端中的命令。如果该命令不存在,则 SELinux 不在您的系统上。如果它确实存在,那么它应该告诉您它是否被强制执行。

    检查 SELinux 策略是否是原因 对于这个问题,您可以尝试暂时关闭它。但是要小心,因为这将完全禁用保护。不要在您的生产服务器上执行此操作。
    setenforce 0
    

    如果关闭 SELinux 的问题不再存在,那么这就是根本原因。

    解决它 ,您必须相应地配置 SELinux。

    以下上下文类型将是必要的:
  • httpd_sys_content_t对于您希望服务器能够读取的文件
  • httpd_sys_rw_content_t用于您想要读写访问的文件
  • httpd_log_t用于日志文件
  • httpd_cache_t缓存目录

  • 例如,分配 httpd_sys_content_t上下文类型到您的网站根目录,运行:
    semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
    restorecon -Rv /path/to/root
    

    如果您的文件在主目录中,您还需要打开 httpd_enable_homedirs bool 值:
    setsebool -P httpd_enable_homedirs 1
    

    在任何情况下,SELinux 拒绝访问文件的原因可能有多种,具体取决于您的策略。所以你需要对此进行调查。 Here是专门为 Web 服务器配置 SELinux 的教程。

    3. Symfony

    如果您正在使用 Symfony,并且在上传到服务器时遇到此错误,则可能是因为应用程序的缓存尚未重置,或者是因为 app/cache已上传,或者该缓存尚未清除。

    您可以通过运行以下控制台命令来测试和修复此问题:
    cache:clear
    

    4. Zip 文件中的非 ACSII 字符

    显然,这个错误也可能在调用 zip->close() 时发生。当 zip 中的某些文件的文件名中包含非 ASCII 字符时,例如“é”。

    一个潜在的解决方案是将文件名包裹在 utf8_decode() 中。在创建目标文件之前。

    Fran Cano确定并建议解决此问题的方法

    关于PHP - 无法打开流 : No such file or directory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36577020/

    相关文章:

    php - 从 php 运行可执行文件而不生成 shell

    php - 简单记录到 php 的数据库类/工具包?

    php - 尝试读取文件时页面未加载

    php - 为什么我的文件在尝试使用 PHP 读取时总是为空?

    javascript - 不允许使用 Codeigniter/PHP(405 错误)在 jQuery Blueimp FileUpload 上删除方法?

    PHP date() 针对不同的时间戳返回不同的时区

    javascript - Node.js 需要缓存

    PHP Require 在不同的文件夹中

    ruby - Gem 不加载 config.ru

    c - 几百次运行后 fopen() 内存泄漏