search

Home  >  Q&A  >  body text

PHP - cannot open stream: No such file or directory

<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>
P粉145543872P粉145543872457 days ago585

reply all(2)I'll reply

  • P粉362071992

    P粉3620719922023-08-24 12:18:48

    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 (called vhost.conf). Only server administrators can write to this file. Apache's configuration looks like this

    <Directory /var/www/vhosts/domain.com>
        <IfModule mod_php5.c>
            php_admin_flag engine on
            php_admin_flag safe_mode off
            php_admin_value open_basedir "/var/www/vhosts/domain.com:/tmp:/usr/share/pear:/local/PEAR"
        </IfModule>
    </Directory>

    Ask 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, or httpd (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)

    chmod 777 /path/to/file

    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

    1. 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

      chown apache:apache /path/to/file
    2. This user (and only this user) has access rights. In Linux, a good practice is chmod 600 (only the owner can read and write) or chmod 644 (the owner can write, but everyone can read)

    You can read a broader discussion of Linux/Unix Permissions and Users here

    reply
    0
  • P粉268654873

    P粉2686548732023-08-24 00:48:10

    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:

    require "/path/to/file"


    List


    1. Check the file path for typos

    • Manual inspection (by visually inspecting the path)
    • Or move whatever require* or include* calls into its own variable, echo it, copy it, and try to Access it via:

      $path = "/path/to/file";
      
      echo "Path : $path";
      
      require "$path";

      Then, in the terminal:

      cat <file path pasted>


    2. Check whether the file path of relative and absolute path considerations is correct

    Best Practices:

    To make your script robust when moving content while still generating absolute paths at runtime, you have 2 options:

    1. Use require __DIR__. "/relative/path/from/current/file" . __DIR__ Magic constants Returns the directory of the current file.
    2. Define a SITE_ROOTconstant:

      • Create a file in the root directory of the website directory, such as config.php
      • Write in config.php

        define('SITE_ROOT', __DIR__);
      • In every file that you want to reference the site root folder, include config.php and then use the SITE_ROOT constant anywhere:

        require_once __DIR__."/../config.php";
        ...
        require_once SITE_ROOT."/other/file.php";

    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:

    include "Zend/Mail/Protocol/Imap.php"

    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:

    echo get_include_path();

    You can add folders to it using the following command:

    set_include_path(get_include_path().":"."/path/to/new/folder");


    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< /一>:

    $user = posix_getpwuid(posix_geteuid());
    
    var_dump($user);

    To find the permissions of a file, type the following command in the terminal:

    ls -l <path/to/file>

    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:

    1. open_basedir
      • If this is set, PHP will not be able to access any files outside the specified directory (not even through symbolic links).
      • However, the default behavior is to not set it, in which case there is no limit
      • You can call phpinfo() or use ini_get("open_basedir")
      • You can change the settings by editing the php.ini file or the httpd.conf file
    2. Safe Mode
      • If this feature is enabled, there may be restrictions. However, this has been removed in PHP 5.4. If you're still using a version that supports safe mode, please upgrade to a still-supported version of PHP. < /里>
    3. allow_url_fopen and allow_url_include
      • This only works when including or opening files via a network process (e.g. http://), not when trying to include files on the local file system
      • You can use ini_get("allow_url_include") Check and use ini_set("allow_url_include", "1") Set


    extreme 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:

    require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"

    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:

    include "Zend/Mail/Protocol/Exception.php"

    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.

    setenforce 0

    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 read
    • httpd_sys_rw_content_t For the file you want read and write access to
    • httpd_log_t For log files
    • httpd_cache_t Used for cache directory

    For example, to assign the httpd_sys_content_t context type to your website root, run:

    semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
    restorecon -Rv /path/to/root

    If your files are located in your home directory, you will also need to turn on httpd_enable_homedirs Boolean:

    setsebool -P httpd_enable_homedirs 1

    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:

    cache:clear


    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< /p>

    reply
    0
  • Cancelreply