php-fpm : Got error 'Unable to open primary script : 에러 처리

하늘 No.521 [컴퓨터] 3
php-fpm_Got error Unable to open primary script_에러 처리 Photo-Image
php-fpm : Got error 'Unable to open primary script : 에러 처리

Apache2 + php 로그 상에서 아래와 같은 에러 발생
Got error 'Unable to open primary script: /folders/phpfiles.php (No such file or directory)'


발생 원인 :
원인은 존재하지 않는 php 일 때 apache2 웹서버에서 404 에러를 발생하지 않고 바로 php 로 넘기기 때문
아파치 웹 내장형 php 가 아닌 독립 실행형 PHP-FPM 에서 발생함


발생 원인 체크 :
    Case1 : server 에서 존재하지 않는 html 파일을 주소창에 입력했을 경우
        - Apache 에서 404 에러 발생
        - Apache 웹서버 에러 메세지

    Case2 : server 에서 존재하지 않는 php 파일을 주소창에 입력했을 경우
        - PHP-FPM 에서 발생됨 (apache 에서 발생되지 않음)
        - response code 는 404
        - No such file or directory 메세지
- apache 로그 : [proxy_fcgi:error] Got error Unable to open primary script


해결책 :
아래 참고 사항 중 2번 항목으로 처리
apache2 세팅에서 php 를 프록시로 넘길 때 파일 존재 유무를 검사 후 넘김
파일명, 파일 내용은 php 버전에 따라 다를 수 있음
conf-enabled 폴더내에 php8.3-fpm.conf 파일이 없다면 fpm 설정이 되어 있지 않은 상태임

$ cd /etc/apache2/conf-enabled
$ vi php8.3-fpm.conf

이 부분에서 <If "-f %{REQUEST_FILENAME}"> ... </If>만 추가
    <FilesMatch ".+\.ph(?:ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
    </FilesMatch>

아래와 같이 조건 추가
    <FilesMatch ".+\.ph(?:ar|p|tml)$">
      <If "-f %{REQUEST_FILENAME}">
        SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
      </If>
    </FilesMatch>

저장후
$ service apache2 restart


완료 테스트 :
존재하지 않는 php 를 주소창 입력했을 때 apache 의 404 에러 메세지가 나오며
apache 로그 : [proxy_fcgi:error] Got error Unable to open primary script 생성되지 않음.


정리:
php 확장자의 경우 apache 웹서버가 파일 존재 여부를 체크하지 않고 바로 PHP-FPM으로 넘기는 설정 때문에 웹 서버의 404에러가 아니라 PHP-FPM 의 404 에러가 나옴.
별 문제는 없으나 apache2 의 로그 상에서 계속 남음.
해결하려면 If -f 조건이나 RewriteCond로 존재하는 파일만 PHP-FPM에 전달하게 바꾸면 됨.
- 정상적인 사용이 아닌 크롤러나 해킹 준비로 웹페이지에 없는 링크 (존재하지 않는) php 파일을 조회하기 때문에 에러 메세지가 많아짐


==========
참고 내용

Apache2 + PHP-FPM 환경
존재하지 않는 .php 파일을 요청했는데 → 404가 안 나오고 그냥 PHP-FPM으로 넘겨버림
즉, 아파치가 먼저 "이 파일이 실제로 있는지" 체크하지 않고, 그냥 .php 요청은 다 PHP-FPM에 넘겨버리는 설정이라 발생하는 문제예요.

원인
Apache의 ProxyPassMatch 또는 SetHandler 설정이 .php 요청을 무조건 FastCGI(PHP-FPM)으로 넘기게 되어 있기 때문이에요.
예를 들어 이런 설정이 있다면:

<FilesMatch "\.php$">
    SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
</FilesMatch>

= 이 경우 아파치는 파일이 실제 존재하는지 확인하지 않고 바로 FPM으로 넘겨버림.

해결 방법 (404 에러 나오게 하기)
1. SetHandler 대신 ProxyFCGI + FilesMatch 조건에서 존재 여부 확인

아래처럼 ProxyFCGI 설정을 디렉토리 단위로 걸어야 해요:

<Directory /var/www/html>
    <FilesMatch "\.php$">
        SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
    </FilesMatch>
</Directory>

그리고 FallbackResource 같은 걸 쓰지 않아야 합니다.

2. ProxyFCGIBackendType을 FPM으로 지정하고 Require file-exists

Apache 2.4.10 이상이라면 FilesMatch에서 Require file-exists 조건을 줄 수 있습니다:
<FilesMatch "\.php$">
    <If "-f %{REQUEST_FILENAME}">
        SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
    </If>
</FilesMatch>

이렇게 하면 실제 파일이 존재할 때만 PHP-FPM으로 전달하고, 없으면 아파치가 404를 냅니다.

3. mod_rewrite를 이용해서 파일 없을 때 차단
조금 우회적인 방법이지만 .htaccess 또는 VirtualHost 안에 이렇게도 가능:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ - [R=404,L]

https://SkyMoon.info/a/HeismeNote/521  

스스로를 던지는 선택의 순간, 처음 던져진 자리를 벗어난 것이며 그것으로 의미는 이루어진 것이지. 의미는 결과에 있는 것이 아니라네 [하늘-대화 3 (선택의 의미)]