更新时间:2022-06-15 23:12:56
可能遇到此错误的原因有很多,因此,一份关于首先要检查的内容的良好清单会大有帮助.
There are many reasons why one might run into this error and thus a good checklist of what to check first helps considerably.
假设我们正在对以下行进行故障排除:
Let's consider that we are troubleshooting the following line:
require "/path/to/file"
或将 require*
或 include*
调用的任何内容移动到它自己的变量中,回显它,复制它,然后尝试从终端访问它:
or move whatever is called by require*
or include*
to its own variable, echo it, copy it, and try accessing it from a terminal:
$path = "/path/to/file";
echo "Path : $path";
require "$path";
然后,在终端中:
cat <file path pasted>
/users/tony/htdocs
***做法:
为了使您的脚本在您四处移动时保持稳健,同时在运行时仍生成绝对路径,您有两个选择:
In order to make your script robust in case you move things around, while still generating an absolute path at runtime, you have 2 options :
require __DIR__ ./relative/path/from/current/file"
.__DIR__
魔术常量 返回当前文件的目录.自己定义一个 SITE_ROOT
常量:
config.php
在config.php
中,写
define('SITE_ROOT', __DIR__);
在您要引用站点根文件夹的每个文件中,包含 config.php
,然后在您喜欢的任何位置使用 SITE_ROOT
常量:>
in every file where you want to reference the site root folder, include config.php
, and then use the SITE_ROOT
constant wherever you like :
require_once __DIR__."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
这 2 种做法还使您的应用程序更具可移植性,因为它不依赖于包含路径之类的 ini 设置.
These 2 practices also make your application more portable because it does not rely on ini settings like the include path.
另一种包含文件的方法,既不是相对也不是绝对绝对,是依赖 包含路径.库或框架(例如 Zend 框架)通常就是这种情况.
Another way to include files, neither relatively nor purely absolutely, is to rely on the include path. This is often the case for libraries or frameworks such as the Zend framework.
这样的包含看起来像这样:
Such an inclusion will look like this :
include "Zend/Mail/Protocol/Imap.php"
在这种情况下,您需要确保Zend"所在的文件夹是包含路径的一部分.
In that case, you will want to make sure that the folder where "Zend" is, is part of the include path.
您可以使用以下命令检查包含路径:
You can check the include path with :
echo get_include_path();
您可以使用以下命令向其中添加文件夹:
You can add a folder to it with :
set_include_path(get_include_path().":"."/path/to/new/folder");
这可能是因为运行服务器进程(Apache 或 PHP)的用户根本没有读取或写入该文件的权限.
It might be that all together, the user running the server process (Apache or PHP) simply doesn't have permission to read from or write to that file.
要检查服务器在哪个用户下运行,您可以使用 posix_getpwuid :
To check under what user the server is running you can use posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
要查看文件的权限,请在终端中键入以下命令:
To find out the permissions on the file, type the following command in the terminal:
ls -l <path/to/file>
并查看权限符号
如果上述方法均无效,则问题可能是某些 PHP 设置禁止它访问该文件.
If none of the above worked, then the issue is probably that some PHP settings forbid it to access that file.
三个设置可能相关:
phpinfo()
来检查> 或使用 ini_get("open_basedir")
ini_get("allow_url_include")
检查并用 ini_set("allow_url_include", "1")
ini_get("allow_url_include")
and set with ini_set("allow_url_include", "1")
如果以上都不能诊断问题,以下是可能发生的一些特殊情况:
If none of the above enabled to diagnose the problem, here are some special situations that could happen :
您可能会使用相对或绝对路径包含一个库,例如 Zend 框架.例如:
It can happen that you include a library, for example, the Zend framework, using a relative or absolute path. For example :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
但是你仍然会遇到同样的错误.
But then you still get the same kind of error.
这可能是因为您(成功)包含的文件本身具有另一个文件的包含语句,而第二个包含语句假定您已将该库的路径添加到包含路径中.
This could happen because the file that you have (successfully) included, has itself an include statement for another file, and that second include statement assumes that you have added the path of that library to the include path.
例如,前面提到的 Zend 框架文件可能包含以下内容:
For example, the Zend framework file mentioned before could have the following include :
include "Zend/Mail/Protocol/Exception.php"
既不是相对路径的包含,也不是绝对路径的包含.假设 Zend 框架目录已添加到包含路径中.
which is neither an inclusion by relative path, nor by absolute path. It is assuming that the Zend framework directory has been added to the include path.
在这种情况下,唯一可行的解决方案是将目录添加到包含路径中.
In such a case, the only practical solution is to add the directory to your include path.
如果您运行的是安全增强型 Linux,则可能是由于拒绝从服务器访问文件而导致问题的原因.
If you are running Security-Enhanced Linux, then it might be the reason for the problem, by denying access to the file from the server.
要检查您的系统是否启用了 SELinux,请在终端中运行 sestatus
命令.如果该命令不存在,则说明 SELinux 不在您的系统上.如果它确实存在,那么它应该告诉您它是否被强制执行.
To check whether SELinux is enabled on your system, run the sestatus
command in a terminal. If the command does not exist, then SELinux is not on your system. If it does exist, then it should tell you whether it is enforced or not.
要检查 SELinux 策略是否是问题的原因,您可以尝试暂时将其关闭.但是要小心,因为这将完全禁用保护.请勿在您的生产服务器上执行此操作.
To check whether SELinux policies are the reason for the problem, you can try turning it off temporarily. However be CAREFUL, since this will disable protection entirely. Do not do this on your production server.
setenforce 0
如果关闭 SELinux 的问题不再存在,那么这就是根本原因.
If you no longer have the problem with SELinux turned off, then this is the root cause.
要解决它,您必须相应地配置 SELinux.
To solve it, you will have to configure SELinux accordingly.
需要以下上下文类型:
httpd_sys_content_t
用于您希望服务器能够读取的文件httpd_sys_rw_content_t
用于您想要读写访问的文件httpd_log_t
用于日志文件httpd_cache_t
缓存目录httpd_sys_content_t
for files that you want your server to be able to readhttpd_sys_rw_content_t
for files on which you want read and write accesshttpd_log_t
for log fileshttpd_cache_t
for the cache directory例如,要将 httpd_sys_content_t
上下文类型分配给您的网站根目录,请运行:
For example, to assign the httpd_sys_content_t
context type to your website root directory, run :
semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
如果您的文件位于主目录中,您还需要打开 httpd_enable_homedirs
布尔值:
If your file is in a home directory, you will also need to turn on the httpd_enable_homedirs
boolean :
setsebool -P httpd_enable_homedirs 1
无论如何,根据您的政策,SELinux 拒绝访问文件的原因可能有多种.所以你需要对此进行调查.这里 是专门为 Web 服务器配置 SELinux 的教程.
In any case, there could be a variety of reasons why SELinux would deny access to a file, depending on your policies. So you will need to enquire into that. Here is a tutorial specifically on configuring SELinux for a web server.
如果您正在使用 Symfony,并且在上传到服务器时遇到此错误,则可能是由于 app/cache
已上传,或者应用程序的缓存尚未重置,或者该缓存尚未清除.
If you are using Symfony, and experiencing this error when uploading to a server, then it can be that the app's cache hasn't been reset, either because app/cache
has been uploaded, or that cache hasn't been cleared.
您可以通过运行以下控制台命令来测试和修复此问题:
You can test and fix this by running the following console command:
cache:clear
显然,当 zip 中的某些文件的文件名中包含非 ASCII 字符(例如é")时,调用 zip->close()
时也会发生此错误.
Apparently, this error can happen also upon calling zip->close()
when some files inside the zip have non-ASCII characters in their filename, such as "é".
一个潜在的解决方案是在创建目标文件之前将文件名包裹在 utf8_decode()
中.
A potential solution is to wrap the file name in utf8_decode()
before creating the target file.
感谢 Fran Cano 发现并提出解决此问题的建议
Credits to Fran Cano for identifying and suggesting a solution to this issue