Programming

PHP-스트림을 열지 못했습니다 : 해당 파일이나 디렉토리가 없습니다

procodes 2020. 6. 19. 21:26
반응형

PHP-스트림을 열지 못했습니다 : 해당 파일이나 디렉토리가 없습니다


PHP 스크립트에서 호출 여부 include(), require(), fopen()등, 또는 이들의 유도체 include_once, require_once또는 심지어, move_uploaded_file()하나는 종종 오류 또는 경고로 실행 :

스트림을 열지 못했습니다 : 해당 파일이나 디렉토리가 없습니다.

문제의 근본 원인을 빨리 찾는 좋은 방법은 무엇입니까?


이 오류가 발생할 수있는 여러 가지 이유가 있으므로 먼저 확인해야 할 사항에 대한 점검표가 상당히 도움이됩니다.

다음 줄의 문제를 해결한다고 가정 해 보겠습니다.

require "/path/to/file"


점검표


1. 파일 경로에 오타가 있는지 확인

  • 수동으로 확인 (경로를 시각적으로 확인)
  • 또는 호출 한 것을 자신의 변수 로 옮기 require*거나 include*복사하고 복사 한 다음 터미널에서 액세스 해보십시오.

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

    그런 다음 터미널에서 :

    cat <file path pasted>
    


2. 상대 경로와 절대 경로를 고려하여 파일 경로가 올바른지 확인하십시오.

  • 슬래시 "/"로 시작하면 웹 사이트 폴더의 루트 (문서 루트)가 아니라 서버의 루트입니다.
    • 예를 들어, 웹 사이트 디렉토리는 /users/tony/htdocs
  • 슬래시로 시작하지 않으면 포함 경로 (아래 참조)에 의존하거나 경로가 상대적입니다. 상대적인 경우 PHP는 현재 작업 디렉토리 의 경로를 상대적으로 계산 합니다.
    • 따라서 웹 사이트 루트의 경로 또는 입력하는 파일과 관련이 없습니다.
    • 따라서 항상 절대 파일 경로를 사용하십시오

모범 사례 :

런타임시 절대 경로를 생성하면서 주위를 이동하는 경우 스크립트를 강력하게 만들려면 다음 두 가지 옵션이 있습니다.

  1. 사용하십시오 require __DIR__ . "/relative/path/from/current/file". __DIR__마법 상수는 현재 파일의 디렉토리를 반환합니다.
  2. 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";
      

이 두 가지 방법은 포함 경로와 같은 ini 설정에 의존하지 않기 때문에 응용 프로그램의 이식성을 향상시킵니다.


3. 포함 경로 확인

상대적으로 또는 절대적으로 절대적으로 파일을 포함하지 않는 또 다른 방법은 include 경로 에 의존하는 것 입니다. 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>

and look at permission symbolic notation


5. Check PHP settings

If none of the above worked, then the issue is probably that some PHP settings forbid it to access that file.

Three settings could be relevant :

  1. open_basedir
    • If this is set PHP won't be able to access any file outside of the specified directory (not even through a symbolic link).
    • However, the default behavior is for it not to be set in which case there is no restriction
    • This can be checked by either calling phpinfo() or by using ini_get("open_basedir")
    • You can change the setting either by editing your php.ini file or your httpd.conf file
  2. safe mode
    • if this is turned on restrictions might apply. However, this has been removed in PHP 5.4. If you are still on a version that supports safe mode upgrade to a PHP version that is still being supported.
  3. allow_url_fopen and allow_url_include
    • this applies only to including or opening files through a network process such as http:// not when trying to include files on the local file system
    • this can be checked with ini_get("allow_url_include") and set with ini_set("allow_url_include", "1")


Corner cases

If none of the above enabled to diagnose the problem, here are some special situations that could happen :


1. The inclusion of library relying on the include path

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.

For example, the Zend framework file mentioned before could have the following include :

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

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.


2. SELinux

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.

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.

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

If you no longer have the problem with SELinux turned off, then this is the root cause.

To solve it, you will have to configure SELinux accordingly.

The following context types will be necessary :

  • httpd_sys_content_t for files that you want your server to be able to read
  • httpd_sys_rw_content_t for files on which you want read and write access
  • httpd_log_t for log files
  • httpd_cache_t for the cache directory

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

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

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.


3. Symfony

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


4. Non ACSII characters inside Zip file

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 "é".

A potential solution is to wrap the file name in utf8_decode() before creating the target file.

Credits to Fran Cano for identifying and suggesting a solution to this issue


To add to the (really good) existing answer

Shared Hosting Software

open_basedir is one that can stump you because it can be specified in a web server configuration. While this is easily remedied if you run your own dedicated server, there are some shared hosting software packages out there (like Plesk, cPanel, etc) that will configure a configuration directive on a per-domain basis. Because the software builds the configuration file (i.e. httpd.conf) you cannot change that file directly because the hosting software will just overwrite it when it restarts.

With Plesk, they provide a place to override the provided httpd.conf called vhost.conf. Only the server admin can write this file. The configuration for Apache looks something 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>

Have your server admin consult the manual for the hosting and web server software they use.

File Permissions

It's important to note that executing a file through your web server is very different from a command line or cron job execution. The big difference is that your web server has its own user and permissions. For security reasons that user is pretty restricted. Apache, for instance, is often apache, www-data or httpd (depending on your server). A cron job or CLI execution has whatever permissions that the user running it has (i.e. running a PHP script as root will execute with permissions of root).

A lot of times people will solve a permissions problem 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 then this isn't such a big deal, but if you're on a shared hosting environment you've just given everyone on your server access.

What you need to do is determine the user(s) that need access and give only those them access. Once you know which users need access you'll want to make sure that

  1. That user owns the file and possibly the parent directory (especially the parent directory if you want to write files). In most shared hosting environments this won't be an issue, because your user should own all the files underneath your root. A Linux example is shown below

    chown apache:apache /path/to/file
    
  2. The user, and only that user, has access. In Linux, a good practice would be chmod 600 (only owner can read and write) or chmod 644 (owner can write but everyone can read)

You can read a more extended discussion of Linux/Unix permissions and users here


  1. Look at the exact error

My code worked fine on all machines but only on this one started giving problem (which used to work find I guess). Used echo "document_root" path to debug and also looked closely at the error, found this

Warning: include(D:/MyProjects/testproject//functions/connections.php): failed to open stream:

You can easily see where the problems are. The problems are // before functions

$document_root = $_SERVER['DOCUMENT_ROOT'];
echo "root: $document_root";
include($document_root.'/functions/connections.php');

So simply remove the lading / from include and it should work fine. What is interesting is this behaviors is different on different versions. I run the same code on Laptop, Macbook Pro and this PC, all worked fine untill. Hope this helps someone.

  1. Copy past the file location in the browser to make sure file exists. Sometimes files get deleted unexpectedly (happened with me) and it was also the issue in my case.

Add script with query parameters

That was my case. It actually links to question #4485874, but I'm going to explain it here shortly.
When you try to require path/to/script.php?parameter=value, PHP looks for file named script.php?parameter=value, because UNIX allows you to have paths like this.
If you are really need to pass some data to included script, just declare it as $variable=... or $GLOBALS[]=... or other way you like.


Samba Shares

If you have a Linux test server and you work from a Windows Client, the Samba share interferes with the chmod command. So, even if you use:

chmod -R 777 myfolder

on the Linux side it is fully possible that the Unix Group\www-data still doesn't have write access. One working solution if your share is set up that Windows admins are mapped to root: From Windows, open the Permissions, disable Inheritance for your folder with copy, and then grant full access for www-data.


Another possible cause: Renaming and/or moving files while in a text editor. I went through all the steps above without success until I deleted the file that kept throwing this error and created a new one, which fixed the issue.

참고URL : https://stackoverflow.com/questions/36577020/php-failed-to-open-stream-no-such-file-or-directory

반응형