PHP - cannot open stream: No such file or directory
P粉145543872
2023-08-23 16:30:33
<p>In a PHP script, whether you call <code>include()</code>, <code>require()</code>, <code>fopen()</code> or its derived classes, such as <code> include_once</code>, <code>require_once</code>, or even <code>move_uploaded_file()</code>, you will often encounter errors or warnings: < /p>
<blockquote>
<p>Cannot open stream: No such file or directory. </p>
</blockquote>
<p>What is a good process for quickly finding the root cause of a problem? </p>
Add to (very good) existing answer
Shared hosting software
open_basedir
may stump you as it can be specified in the web server configuration. While this is easily solved if you run your own dedicated server, there are shared hosting packages (like Plesk, cPanel, etc.) that allow configuration directives on a per-domain basis. Since the software builds the configuration file (i.e.httpd.conf
), you cannot change this file directly as the hosting software will just overwrite it on restart.With Plesk, they provide a location to override the provided
httpd.conf
(calledvhost.conf
). Only server administrators can write to this file. Apache's configuration looks like thisAsk your server administrator to consult the manuals for the hosting and web server software they use.
File Permissions
It is important to note that executing files via a web server is very different from command line or cron job execution. The biggest difference is that your web server has its own users and permissions. This user is heavily restricted for security reasons. For example, Apache is usually
apache
,www-data
, orhttpd
(depending on your server). A cron job or CLI execution has whatever permissions the user running it has (i.e. a PHP script run as root will execute with root permissions).Many times people will solve permission issues by doing the following (Linux example)
This is not a smart idea because the file or directory is now world-writable. If you own the server and are the only user, this isn't a big deal, but if you're in a shared hosting environment, you're granting access to everyone on the server.
What you need to do is identify the users who need access and grant access only to them. Once you know which users need access, you need to make sure
This user owns the file and may own the parent directory (especially the parent directory if you are writing to the file). In most shared hosting environments this won't be a problem as your user should own all files in the root directory. A Linux example is shown below
This user (and only this user) has access rights. In Linux, a good practice is
chmod 600
(only the owner can read and write) orchmod 644
(the owner can write, but everyone can read)You can read a broader discussion of Linux/Unix Permissions and Users here
There are many reasons why you might encounter this error, so a good checklist of what to check first is helpful.
Assume we are troubleshooting the following line:
List
1. Check the file path for typos
Or move whatever
require*
orinclude*
calls into its own variable, echo it, copy it, and try to Access it via:Then, in the terminal:
2. Check whether the file path of relative and absolute path considerations is correct
/users/tony/htdocs
Best Practices:
To make your script robust when moving content while still generating absolute paths at runtime, you have 2 options:
require __DIR__. "/relative/path/from/current/file"
.__DIR__
Magic constants Returns the directory of the current file.Define a
SITE_ROOT
constant:config.php
Write
in
config.phpIn every file that you want to reference the site root folder, include
config.php
and then use theSITE_ROOT
constant anywhere: p>These 2 practices also make your application more portable since it does not rely on ini settings such as include paths.
3. Check your include paths
Another way to include files, which is neither relative nor purely absolute, is to rely on the include path. This is often the case with libraries or frameworks such as the Zend Framework.
Such an include would look like this:
In this case, you need to make sure that the folder where "Zend" is located is part of the include path.
You can check the include path using the following command:
You can add folders to it using the following command:
4. Check if your server has access to the file
To summarize, the user running the server process (Apache or PHP) may not have permission to read or write the file at all.
To check under which user the server is running, you can use posix_getpwuid:
To find the permissions of a file, type the following command in the terminal:
and viewpermission notation
5. Check PHP settings
If none of the above methods work, the problem may be that some PHP settings prevent it from accessing the file.
Three settings may be relevant:
phpinfo()
进行检查> or useini_get("open_basedir")
ini_get("allow_url_include")
Check and useini_set("allow_url_include", "1")
Setextreme case
If none of the above methods can diagnose the problem, some of the following special situations may occur:
1. Includes for libraries that depend on include paths
You might include a library, such as the Zend Framework, using a relative or absolute path. For example:
But you will still encounter the same type of errors.
This happens because the file you (successfully) include itself has an include statement from another file, and the second include statement assumes that you have added the path to the library to the include path.
For example, the Zend framework file mentioned earlier might contain the following:
Neither included through relative paths nor included through absolute paths. It is assumed that the Zend framework directory has been added to the include path.
In this case, the only practical solution is to add the directory to the include path.
2. SELinux
If you are running security-enhanced Linux, this may be the cause of the problem, as access to the file from the server is denied.
To check if SELinux is enabled on your system, run the
sestatus
command in the terminal. If this command does not exist, SELinux does not exist on your system. If it does exist, then it should tell you whether it is enforced.To check if the SELinux policy is the cause of the problem, you can try turning it off temporarily. But be careful as this will completely disable protection. Don't do this on a production server.
If you no longer have problems after turning off SELinux, then this is the root cause.
To resolve this issue, you must configure SELinux accordingly.
The following context types are required:
httpd_sys_content_t
For files you want the server to be able to readhttpd_sys_rw_content_t
For the file you want read and write access tohttpd_log_t
For log fileshttpd_cache_t
Used for cache directoryFor example, to assign the
httpd_sys_content_t
context type to your website root, run:If your files are located in your home directory, you will also need to turn on
httpd_enable_homedirs
Boolean:Regardless, there may be several reasons why SELinux denies access to a file, depending on your policy. So you need to investigate this. Here is a tutorial specifically for configuring SELinux for web servers.
3. symphony
If you are using Symfony and you encounter this error when uploading to the server, it is possible that the app's cache has not been reset because
app/cache
has been uploaded, or that the cache has not been cleared.You can test and fix this issue by running the following console command:
4. Non-ACSII characters in Zip files
Apparently this error can also occur when calling
zip->close()
when some of the files in the zip contain non-ASCII characters (e.g. "é") in their filenames.A possible solution is to wrap the filename in
utf8_decode()
before creating the target file.Thanks Fran Cano for identifying this problem and proposing a solution