PHP-FPM環境におけるNginxの「Primary script unknown」エラーの修正方法

beginner Nginx2026-04-19| Linux (Ubuntu 22.04, Debian 12, CentOS 9, RHEL 9), Nginx 1.18+, PHP-FPM (7.4, 8.0, 8.1, 8.2, 8.3)

Error Message

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
#nginx#php-fpm#devops#トラブルシューティング#linuxサーバー

エラーの構造

Webアプリケーションにアクセスすると、冷ややかな「404 Not Found」ページが表示されます。ファイルはディスク上に存在するのに、Nginxがそれを提供してくれません。/var/log/nginx/error.logにあるエラーログを素早く確認すると、次のようなイライラさせるメッセージが表示されています。

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

エラーの背景

このエラーは、NginxとPHP-FPMの間の通信障害を示しています。Nginxはゲートキーパーとして動作し、リクエストを受け取ってPHPプロセッサに渡します。しかし、PHP-FPMはNginxから提供されたファイルパスを見つけることができないため、「not found(見つかりません)」と応答します。多くの場合、これは3つの設定の不備のいずれかに集約されます。

  • PHP-FPMに渡される SCRIPT_FILENAME 変数が存在しないパスを指している。
  • root ディレクティブが誤った設定ブロック内に閉じ込められている。
  • PHP-FPMプロセスにディレクトリを読み取るために必要な権限がない。

ステップバイステップの解決策

1. SCRIPT_FILENAMEパラメータの監査

最も頻繁な原因は、fastcgi_param SCRIPT_FILENAME の設定ミスです。通常 /etc/nginx/sites-available/example.com にあるサイト設定ファイルを開きます。

PHPの location ブロックを探します。以下のようになっているはずです。

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

修正方法: SCRIPT_FILENAME$document_root$fastcgi_script_name を使用していることを確認してください。もし /var/www/html$fastcgi_script_name のようにパスをハードコードしている場合は、すべての文字を検証してください。フォルダ名のタイポ(打ち間違い)が1つあるだけで、404がトリガーされます。

2. rootディレクティブの罠を回避する

root ディレクティブの配置ミスは、よくある落とし穴です。location / ブロック内に root を定義すると、PHPブロックはそれを継承しません。その結果、NginxがPHP-FPMにリクエストを渡す際、$document_root 変数が空になってしまいます。

避けるべき間違い:

server {
    listen 80;
    server_name example.com;

    location / {
        root /var/www/my-app/public; # 誤り:スコープが限定されている
        index index.php;
    }

    location ~ \.php$ {
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        ...
    }
}

正しい方法: root ディレクティブを server レベルに移動します。これにより、ファイル内のすべての location ブロックに適用されるようになります。

server {
    listen 80;
    server_name example.com;
    root /var/www/my-app/public; # 正解:グローバルスコープ

    location / {
        index index.php;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}

3. 権限のボトルネックを解消する

PHP-FPMは権限に対して非常に厳格です。通常、ファイルをアップロードしたユーザーではなく、www-dataphp-fpm として実行されます。PHPワーカーがディレクトリツリーを「辿る」ことができない場合、スクリプトを unknown として報告します。

以下のコマンドでPHPユーザーを特定します:

ps aux | grep php-fpm

このユーザーがPHPファイルへの読み取り権限と、すべての親ディレクトリへの実行権限を持っていることを確認してください。標準的なUbuntuのセットアップでは、以下のコマンドで所有権と権限を素早くリセットできます:

sudo chown -R www-data:www-data /var/www/my-app
sudo find /var/www/my-app -type d -exec chmod 755 {} \;
sudo find /var/www/my-app -type f -exec chmod 644 {} \;

4. RHEL/CentOSでSELinuxを制御する

Red Hat系のシステムでは、SELinuxが「静かな殺し屋」になることがよくあります。Linuxの権限が完璧な 777 であっても、Nginxをブロックすることがあります。一時的に permissive モードに切り替えて、これをテストします:

sudo setenforce 0

もしサイトが突然動作するようになったら、SELinuxが障壁となっていました。強制モード(enforcement)に戻し、Webフォルダに正しいセキュリティコンテキストを適用します:

sudo setenforce 1
sudo chcon -Rt httpd_sys_content_t /var/www/my-app

変更の適用

構文をテストせずにNginxを再起動しないでください。セミコロンが1つ欠けているだけで、サーバー全体がオフラインになる可能性があります。

sudo nginx -t

テストに合格したら、サービスをリロードして修正を適用します:

sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm

ブラウザを更新してください。これでPHPアプリケーションが正しく読み込まれるはずです。

トラブルシューティングのプロのヒント

  • シンボリックリンクに注意: Capistranoのようなデプロイツールを使用している場合は、Nginxがシンボリックリンクを辿れるように設定されているか確認してください。必要に応じて、設定に disable_symlinks off; を記述します。
  • ソケットパスを確認: fastcgi_pass/etc/php/8.2/fpm/pool.d/www.conf にある実際のソケットファイルと一致しているか確認してください。バージョンの不一致(例:設定では 8.1 だが 8.2 がインストールされている)は、よくある悩みの種です。
  • ドキュメントルートの正確性: fastcgi_param において、root ディレクティブにすでにスラッシュが含まれている場合は、末尾のスラッシュを避けてください。二重のスラッシュ(例:/var/www//index.php)は、特定のPHP-FPMバージョンを混乱させることがあります。

Related Error Notes