在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
最佳实践:
为了使您的脚本在您四处移动时保持稳健,同时在运行时仍生成绝对路径,您有 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 设置禁止它访问该文件。
三个设置可能相关:
phpinfo()
来检查。或使用 ini_get("open_basedir")
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/