69

SO has many articles mentioning this error code:

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

That probably means that this error message is more or less useless.

The message is telling us that the FastCGI handler doesn't like whatever it was sent for some reason. The problem is that sometimes we have no idea what the reason is.

So I'm re-stating the question -- How do we debug this error code?

Consider the situation where we have a very simple site, with just the phpinfo.php file. Additionally, there is a very simple nginx config, as follows:

server {
    server_name testsite.local;

    root /var/local/mysite/;

    location / {
        index index.html index.htm index.php;
    }

    location ~ \.php$ {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass  fastcgi_backend;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

How can we see output/log exactly what fastcgi_params got sent to the script?

How can we see the actual error message? In my case, I'm using php-fpm. It has no info in the log about this error. The logs do not append any rows for this error. Is there a verbose mode for php-fpm?

/var/log/php-fpm/error.log
/var/log/php-fpm/www-error.log

I've tried to set this in the php-fpm.conf file

log_level = notice

and this in the php-fpm.d/www.conf file:

catch_workers_output = yes
Jesse Nickles
  • 1,435
  • 1
  • 17
  • 25
101010
  • 14,866
  • 30
  • 95
  • 172

10 Answers10

124

To answer your question:

  1. in php-fpm.d/www.conf file:

set the access.log entry:

access.log = /var/log/$pool.access.log
  1. restart php-fpm service.

  2. try to access your page

  3. cat /var/log/www.access.log, you will see access logs like:

- - 10/Nov/2016:19:02:11 +0000 "GET /app.php" 404 - - 10/Nov/2016:19:02:37 +0000 "GET /app.php" 404

To resolve "Primary script unknown" problem:

  • if you see "GET /" without a correct php file name, then it's your nginx conf problem.

  • if you see "GET /app.php" with 404, it means nginx is correctly passing the script file name but php-fpm failed to access this file (user "php-fpm:php-fpm" don't have access to your file, which trapped me for 3 hours)

Hope my answer helps.

Nicolas
  • 414
  • 4
  • 7
Shengjie YU
  • 1,364
  • 1
  • 10
  • 5
  • 2
    i know this is really old answer, but this one makes more sense to me than the the other answer. For me, point 2 seems to be the case but i dont have any user "php-fpm". My current user has access to the file. Not sure why its happening even now. Any help would be appreciated. – Shadab Faiz Jul 12 '18 at 13:28
  • 5
    If you really want to see the primary script set by nginx you should enable the `access format` line in the www.conf file. It is more verbose than the default and contains `%f` and this is the real script file. `; %f: script filename ; Default: "%R - %u %t \"%m %r\" %s" access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"` – wiktor Oct 02 '18 at 14:23
  • 1
    Don't forget to restart your php-fpm (eg. `systemctl restart php7.3-fpm`) – Melroy van den Berg Jan 03 '19 at 02:59
  • 1
    I have this error message from nginx intermittently. Sometimes I get primary script unknown and a 404, sometimes I don't and I get a 200. Either way I get the correct script file – tedders Oct 08 '19 at 18:22
  • 1
    In my case, the user was www-data instead of php-fpm – cgaldiolo Oct 25 '19 at 15:31
  • I my silly case, the root value in my nginx server block was wrong and fpm could not find index.php – cucu8 Apr 16 '20 at 10:13
  • I faced the similar problem while trying to run `php` from `lighttpd` and made the mistake of setting incorrect user and group in `/etc/php-fpm.d/www.conf`. For `lighttpd` server, both user and group should be set to `lighttpd`. Don't forget to restart `php-fpm.service`. – Soumya Kanti Nov 03 '20 at 17:53
  • it should be access_log and not error_log – gdm Dec 30 '20 at 22:21
  • this solved it for me, the issue was the php-fpm process does not have the correct linux permissions to access the directories/files of the php website. In my case, the directories were given R and W permission , missing the X permission, which prevented php-fpm from going into the directories – sutoL Jan 07 '21 at 02:06
  • gave permission to www-data and sat the user and password to www-data and it's not working – Rose Riyadh May 19 '22 at 15:07
  • As of 2022, what happens if this was run on Docker (Nginx and PHP-FPM)? Still getting the error on the file with 404? :( – Louie Miranda Jun 25 '22 at 05:57
  • In my case it was mismatch of socket file path between php/fpm/pool.d/www.conf and /etc/nginx/conf.d/example.conf – jayaprakash R Sep 10 '22 at 12:02
  • Do you have to restart php-fpm or is it enough to reload? I always find restart a bit risky in case of introducing a syntax error. The process will then not run. In case of reload, it will output an error. – Sybille Peters Mar 16 '23 at 11:10
10

As request is processed by the php worker, you can trace the php worker to get the reason.

To make it easy to locate which worker process the request, set only one worker in php-fpm's conf file.

pm.max_children = 1
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 1

Get php work pid with $ps -aef | grep -v grep | grep php

root     28879     1  0 Apr12 ?        00:00:02 php-fpm: master process (/etc/php-fpm.conf)
www      28880 28879  0 Apr12 ?        00:00:24 php-fpm: pool www

Then trace the work process with $ sudo strace -p 28880, and then do the request, and you will see the trace output like below

strace: Process 28880 attached
accept(10,

{sa_family=AF_UNIX}, [112->2]) = 4
poll([{fd=4, events=POLLIN}], 1, 5000)  = 1 ([{fd=4, revents=POLLIN}])
times({tms_utime=1388, tms_stime=1099, tms_cutime=0, tms_cstime=0}) = 1336709044
read(4, "\1\1\0\1\0\10\0\0", 8)         = 8
read(4, "\0\1\0\0\0\0\0\0", 8)          = 8
read(4, "\1\4\0\1\4U\3\0", 8)           = 8
read(4, "\17DSCRIPT_FILENAME/data/HQ/SC_Edu"..., 1112) = 1112
read(4, "\1\4\0\1\0\0\0\0", 8)          = 8
lstat("/data/www/public/st/mn/dst.php", 0x7ffce98d7170) = -1 ENOENT (No such file or directory)
stat("/data/www/public/st/mn", 0x7ffce98d9580) = -1 ENOENT (No such file or directory)
stat("/data/www/public/st", 0x7ffce98d9580) = -1 ENOENT (No such file or directory)
stat("/data/www/public", {st_mode=S_IFDIR|0774, st_size=4096, ...}) = 0
...

From the trace output, it shows script file /data/www/public/st/mn/dst.php not exit

LF00
  • 27,015
  • 29
  • 156
  • 295
4

The issue caused by Nginx's fastcgi_pass not right.

You can check the following:

Open file: /etc/php-fpm.conf (systemctl status php-fpm to find it) and find pid = after = is a path you need to compare with your path listen = in file /etc/php-fpm.d/www.conf 2 path have to the same location.

for example:

pid = /run/php-fpm/php-fpm.pid

listen = /run/php-fpm/php-fpm.sock;

My old path listen = /var/run/php-fpm/php-fpm.sock; and I changed to /run/php-fpm/php-fpm.sock; then restart php-fpm then it run well.

Thanh
  • 51
  • 4
  • You gave me the clarity and my case was exactly as yours mine socket file path mismatch in fpm www.conf and nginx webconfig file – jayaprakash R Sep 10 '22 at 12:06
3

For me it was a permission issue & I had to change user & group in php-fpm/www.conf

change values to your username & group _www e.g

user = aqib
group = _www
Arghya Sadhu
  • 41,002
  • 9
  • 78
  • 107
Aqib
  • 304
  • 3
  • 5
2

In my case, this error occurs because php-fpm could not find file according to $document_root, which is /etc/nginx/html

By setting

 location ~ \.php$ {
        root /var/www/html;
        fastcgi_index   index.php;
        ...
    }

PHP-FPM can now locate the file correctly.

deejiw
  • 31
  • 5
0

For MacOs users, in case if someone encountered as in my situation:

I had started php service with:

sudo brew start php72

since I have used "sudo" permissions was different. I needed to stop and start php service without sudo.

sudo brew stop php72
brew start php72

Hope helps to someone.

İsmail Atkurt
  • 1,360
  • 1
  • 12
  • 17
0

Check the root's position and also the file existence under it, I met this error because of the Root path TYPO .

herbertD
  • 10,657
  • 13
  • 50
  • 77
0

For me (Oracle Linux 7) it was SELinux that was preventing php-fpm from accessing the file. Red Hat and Centos users may find the same.

runing

sestatus

shows the status of SELinux, for me it was turned on causing the problem. I had tried and implemented all of the other suggested fixes but the error persisted.

I solved it by putting SELinux into permissive mode:

/etc/selinux/config

# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=permissive
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

The rest of my minimal configuration: /etc/nginx/nginx.conf:

user  apache;
worker_processes  1;

events {
}
http {

        include mime.types;
        server {
                listen 80;
                server_name 111.222.111.222; #your ip address
                root /sites/demo;

                index index.php index.html;

                location ~ \.php$ {
                        # pass to php-fpm
                        include fastcgi.conf;
                        include fastcgi_params;
                        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
                }

        }
}

Note: I changed the user to apache which is the user used by php-fpm

/etc/php-fpm.d/www.conf:

 The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
;listen = 127.0.0.1:9000
listen = /run/php-fpm/php-fpm.sock

; Set listen(2) backlog.
; Default Value: 511
;listen.backlog = 511

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server.
; Default Values: user and group are set as the running user
;                 mode is set to 0660
listen.owner = apache
listen.group = apache
listen.mode = 0660

Note: I set listen.owner and listen.group to apache

The permissions on my files and folders are: /sites (root:apache drwxrwxr-x) /sites/demo (root:apache drwxrwxr-x) /sites/demo/index.php (root:apache .rw.rw.r..)

If you look at ps -aux | grep -E "php|nginx" you can see that all of the php-fpm pool processes and the nginx worker process are running as user apache.

If you look at the permissions for the socket file /run/php-fpm/php-fpm.sock you will see that it is owned by apache:apache and srw-rw----

Aidan
  • 1,550
  • 1
  • 13
  • 20
0
sudo systemctl reload php[YOUR.VERSION]-fpm

I had a freshly installed php-fpm and I haven't reboot my Ubuntu. So I just ran this command and this solved the issue.

-1

In my case I also began fighting millions of issues in code in the beginning, but then I looked at the big picture globally. The problem was in the incorrect version of PHP. Ultimately, I went down trying different PHP versions one by one, like so:

fastcgi_pass unix:/run/php/php7.3-fpm.sock

fastcgi_pass unix:/run/php/php5.3-fpm.sock

and then it worked without literally re-developing and changing millions of lines of code. I know it's a bit silly and all, but the new PHP versions absolutely crash everything if it was developed in older style and old PHP ways. It was more important for me to get it to work THAN to run the most most most most most most most most updated version of PHP.

Dennis
  • 1
  • 4
  • 1
    That's very much trial and error with something that should definately be known, i.e. your upstream socket path.. The listen directive in php-fpm config has that value set and if in doubt, check the run dir for the actual socket name... – OldFart Oct 25 '22 at 08:16