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는 현재 작업 디렉토리 의 경로를 상대적으로 계산 합니다.
- 따라서 웹 사이트 루트의 경로 또는 입력하는 파일과 관련이 없습니다.
- 따라서 항상 절대 파일 경로를 사용하십시오
모범 사례 :
런타임시 절대 경로를 생성하면서 주위를 움직일 때 스크립트를 강력하게 만들기 위해 두 가지 옵션이 있습니다.
- 사용하십시오
require __DIR__ . "/relative/path/from/current/file"
.__DIR__
마법 상수는 현재 파일의 디렉토리를 반환합니다. -
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>
권한 기호 표기법을 봅니다.
5. PHP 설정 확인
위의 방법 중 어느 것도 작동하지 않으면 일부 PHP 설정으로 인해 해당 파일에 액세스하는 것이 금지되었을 수 있습니다.
세 가지 설정이 관련 될 수 있습니다.
- open_basedir
- 이것이 설정되면 PHP는 지정된 디렉토리 외부 (심볼릭 링크를 통해서도) 외부의 파일에 접근 할 수 없습니다.
- 그러나 기본 동작은 설정되어 있지 않아야하며,이 경우 제한이 없습니다.
- 이것은 전화
phpinfo()
또는 사용하여 확인할 수 있습니다ini_get("open_basedir")
- php.ini 파일 또는 httpd.conf 파일을 편집하여 설정을 변경할 수 있습니다
- 안전 모드
- 이것이 켜져 있으면 제한이 적용될 수 있습니다. 그러나 이것은 PHP 5.4에서 제거되었습니다. 안전 모드를 지원하는 버전을 계속 사용중인 경우 여전히 지원되는 PHP 버전으로 업그레이드하십시오 .
- allow_url_fopen 및 allow_url_include
- 이것은 로컬 파일 시스템에 파일을 포함하려고 할 때가 아닌 http : //와 같은 네트워크 프로세스를 통해 파일을 포함하거나 여는 경우에만 적용됩니다
- 이것은 확인
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"
그러나 여전히 같은 종류의 오류가 발생합니다.
포함 된 파일 (성공적으로)에 다른 파일에 대한 include 문이 있고 두 번째 include 문은 해당 라이브러리의 경로를 include 경로에 추가했다고 가정하기 때문에 발생할 수 있습니다.
예를 들어 앞에서 언급 한 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
부울 을 켜야합니다 .
setsebool -P httpd_enable_homedirs 1
어쨌든 SELinux가 정책에 따라 파일에 대한 액세스를 거부하는 여러 가지 이유가있을 수 있습니다. 그래서 당신은 그것에 문의해야합니다. 다음 은 웹 서버용 SELinux 구성에 대한 자습서입니다.
3. 심포니
Symfony를 사용 중이고 서버에 업로드 할 때이 오류가 발생하는 경우 업로드 app/cache
되었거나 캐시가 지워지지 않아 앱의 캐시가 재설정되지 않았을 수 있습니다 .
다음 콘솔 명령을 실행하여이를 테스트하고 수정할 수 있습니다.
cache:clear
4. Zip 파일 내의 비 ACSII 문자
zip->close()
zip 내부의 일부 파일에 파일 이름에 ASCII가 아닌 문자 (예 : “é”)가있는 경우 호출 할 때도이 오류가 발생할 수 있습니다 .
잠재적 인 해결책은 utf8_decode()
대상 파일을 작성하기 전에 파일 이름을 랩핑하는 것 입니다.
크레딧 프랜 카노 이 문제에 대한 해결책을 식별하고 제안에 대한
답변
(정말로 좋은) 기존 답변에 추가하려면
공유 호스팅 소프트웨어
open_basedir
웹 서버 구성에서 지정할 수 있기 때문에 사용자를 방해 할 수 있습니다. 고유 한 전용 서버를 실행하면이 문제를 쉽게 해결할 수 있지만 Plesk, cPanel 등과 같은 일부 공유 호스팅 소프트웨어 패키지는 도메인별로 구성 지시문을 구성합니다. 소프트웨어가 구성 파일 (예 :)을 빌드 httpd.conf
하기 때문에 호스팅 소프트웨어는 다시 시작할 때 파일을 덮어 쓰기 때문에 해당 파일을 직접 변경할 수 없습니다.
Plesk를 함께, 그들은 제공된 오버라이드 (override) 할 수있는 장소 제공 httpd.conf
이라고를 vhost.conf
. 서버 관리자 만이 파일을 쓸 수 있습니다. Apache의 구성은 다음과 같습니다
<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>
서버 관리자가 사용하는 호스팅 및 웹 서버 소프트웨어 설명서를 참조하십시오.
파일 권한
웹 서버를 통해 파일을 실행하는 것은 명령 행 또는 크론 작업 실행과 매우 다르다는 점에 유의해야합니다. 가장 큰 차이점은 웹 서버에 자체 사용자 및 권한이 있다는 것입니다. 보안상의 이유로 사용자는 상당히 제한되어 있습니다. 예를 들어 Apache는 종종 apache
( www-data
또는 httpd
서버에 따라)입니다. 크론 작업 또는 CLI 실행에는 사용자가 실행하는 모든 권한이 있습니다 (예 : 루트로 PHP 스크립트를 실행하면 root 권한으로 실행 됨).
많은 사람들이 다음을 수행하여 권한 문제를 해결할 것입니다 (Linux 예제).
chmod 777 /path/to/file
파일이나 디렉토리가 이제 세계 쓰기 가능하기 때문에 이것은 현명한 아이디어가 아닙니다. 서버를 소유하고 있고 유일한 사용자 인 경우에는 큰 문제가되지 않지만 공유 호스팅 환경에있는 경우 서버의 모든 사용자에게 서버 액세스 권한을 부여한 것입니다.
액세스가 필요한 사용자를 결정하고 해당 사용자에게만 액세스 권한을 부여하면됩니다. 어떤 사용자가 액세스해야하는지 알고 나면
-
해당 사용자는 파일 및 상위 디렉토리 (특히 파일을 작성하려는 경우 상위 디렉토리)를 소유합니다 . 대부분의 공유 호스팅 환경에서는 사용자가 루트 아래에있는 모든 파일을 소유해야하므로 문제가되지 않습니다. 리눅스 예제는 아래와 같습니다.
chown apache:apache /path/to/file
-
사용자 및 해당 사용자 만 액세스 할 수 있습니다. 리눅스에서 좋은 습관은
chmod 600
(소유자 만 읽고 쓸 수 있음) 또는chmod 644
(소유자는 쓸 수 있지만 누구나 읽을 수 있음)
답변
- 정확한 오류를 봐
내 코드는 모든 컴퓨터에서 제대로 작동했지만이 코드에서만 문제가 발생하기 시작했습니다. 에코 “document_root”경로를 디버깅에 사용하고 오류를 자세히 살펴 보았습니다.
경고 : include ( D : /MyProjects/testproject//functions/connections.php ) : 스트림을 열지 못했습니다 :
문제가있는 위치를 쉽게 확인할 수 있습니다. 문제는 // 함수 전입니다
$document_root = $_SERVER['DOCUMENT_ROOT'];
echo "root: $document_root";
include($document_root.'/functions/connections.php');
따라서 단순히 래딩 /를 포함에서 제거하면 정상적으로 작동합니다. 흥미로운 점은이 동작이 버전마다 다릅니다. 랩톱, Macbook Pro 및이 PC에서 동일한 코드를 실행하면 모두 정상적으로 작동했습니다. 이것이 누군가를 돕기를 바랍니다.
- 브라우저에서 파일 위치를지나 복사하여 파일이 있는지 확인하십시오. 때로는 파일이 예기치 않게 삭제되고 (나와 함께 발생) 내 경우에도 문제가되었습니다.
답변
쿼리 매개 변수가있는 스크립트 추가
그게 내 사건이야 실제로는 질문 # 4485874 에 연결되지만 여기서는 곧 설명하겠습니다.
을 요구하려고 할 때 path/to/script.php?parameter=value
, PHP는 script.php?parameter=value
UNIX에서 이와 같은 경로를 가질 수 있기 때문에 이라는 파일을 찾습니다 .
당신이 정말로, 포함 된 스크립트로 일부 데이터를 전달해야 할 경우 단지로 선언 $variable=...
또는 $GLOBALS[]=...
당신 같은 또는 다른 방법.
답변
삼바 주식
Linux 테스트 서버가 있고 Windows 클라이언트에서 작업하는 경우 Samba 공유가 chmod 명령을 방해합니다 . 따라서 다음을 사용하더라도
chmod -R 777 myfolder
리눅스 측면에서 유닉스 그룹 \ www-data가 여전히 쓰기 액세스 권한을 가지고 있지 않을 수 있습니다. 공유가 Windows 관리자가 루트에 매핑되도록 설정 한 경우의 한 가지 해결 방법 : Windows에서 권한을 열고 복사하여 폴더의 상속을 비활성화 한 다음 www-data에 대한 모든 액세스 권한을 부여하십시오.
답변
또 다른 가능한 원인 : 텍스트 편집기에서 파일 이름 바꾸기 및 / 또는 파일 이동. 이 오류가 계속 발생하는 파일을 삭제하고 새 파일을 작성하여 문제를 해결하기 전까지 위의 모든 단계를 성공하지 못했습니다.