Primary script unknown 错误解决

错误解决

在 macOS 中配置 nginx+php-fpm 出错,访问 http://localhost/phpinfo.php ,浏览器中的显示是:

File not found.

在 nginx 的 log 中,完整的错误为:

12017/08/01 10:39:54 [error] 50087#0: *15 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /phpinfo.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "localhost"

nginx 配置内容(位于 server 段):

 1location / {
 2    root   /srv/www;
 3    index  index.html index.htm;
 4    autoindex on;
 5}
 6
 7location ~ \.php$ {
 8    include        fastcgi_params;
 9    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
10    fastcgi_pass   127.0.0.1:9000;
11    fastcgi_index  index.php;
12}

首先要判断是 nginx 的问题,还是 php-fpm 的问题。

/etc/php-fpm.conf 中配置:

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

重启 php-fpm,查看 /var/log/php-fpm.www.access.log 的内容:

  • 如果看到类似于 "GET /" 这样的没有包含具体的 php 文件名的 log,则说明可能是 nginx 路径配置问题;
  • 如果看到类似于 "GET /your_php_file.php" 404 这样的 log,则说明可能是 php-fpm 进程无法读取文件。

无法读取文件的原因有很多,可能是文件路径错误,也可能是权限问题。幸运的是,我碰到的是后者:

1127.0.0.1 -  01/Aug/2017:10:39:48 +0800 "GET /phpinfo.php" 404

首先排除权限问题,配置 /etc/php-fpm.conf ,将 user 和 group 设置为 macOS 中我的用户。然后重启 php-fpm 服务。

1user = zrong
2group = staff

错误依旧。

接着怀疑路径问题。我们需要知道 nginx 传给 php-fpm 的具体文件路径是什么,这需要做一些 log 配置。

把下面的配置写入 nginx 配置文件的 http 段:

1log_format scripts '$document_root$fastcgi_script_name > $request';

把下面的配置写入 nginx 配置文件的 server 段:

1access_log /usr/local/var/log/nginx/scripts.log scripts;

重启 nginx 服务,查看 /usr/local/var/log/nginx/scripts.log ,此时真相大白。由于我没有在 location ~ \.php$ 段中配置 root,nginx 默认使用了其安装目录下的 html 作为 root,导致传递的文件路径不正确,php-fpm 无法接收到实际的 php 文件。

我误以为 location / 中配置的 root 会自动向下传递,但我忽略了 location ~ \.php$ 其实与 location / 是平级,没有继承关系。

1/usr/local/Cellar/openresty/1.9.7.4/nginx/html/phpinfo.php > GET /phpinfo.php HTTP/1.1
2/usr/local/Cellar/openresty/1.9.7.4/nginx/html/phpinfo.php > GET /phpinfo.php HTTP/1.1

修改 nginx 配置文件,问题解决:

1location ~ \.php$ {
2    root /srv/www;
3    include        fastcgi_params;
4    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
5    fastcgi_pass   127.0.0.1:9000;
6    fastcgi_index  index.php;
7}

此时查看 /usr/local/var/log/nginx/scripts.log ,内容为:

1/srv/www/phpinfo.php > GET /phpinfo.php HTTP/1.1
2/srv/www/phpinfo.php > GET /phpinfo.php HTTP/1.1

几个小技巧

php-fpm.plist

在 macOS 下应该创建一个 launch plist 文件,将其放在 /Library/LaunchDaemons/zrong.php-fpm.plist

 1<?xml version="1.0" encoding="UTF-8"?>
 2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3<plist version="1.0">
 4<dict>
 5  <key>KeepAlive</key>
 6  <false/>
 7  <key>Label</key>
 8  <string>zrong.php-fpm</string>
 9  <key>ProgramArguments</key>
10  <array>
11    <string>/usr/sbin/php-fpm</string>
12    <string>--fpm-config</string>
13    <string>/etc/php-fpm.conf</string>
14    <string>--nodaemonize</string>
15  </array>
16  <key>RunAtLoad</key>
17  <true/>
18  <key>UserName</key>
19  <string>root</string>
20  <key>WorkingDirectory</key>
21  <string>/var</string>
22  <key>StandardErrorPath</key>
23  <string>/var/log/php-fpm.log</string>
24</dict>
25</plist>

启动:

1sudo launchctl load /Library/LaunchDaemons/zrong.php-fpm.plist

停止:

1sudo launchctl unload /Library/LaunchDaemons/zrong.php-fpm.plist

在 macOS 上重启 php-fpm

需要注意的是,php-fpm 默认是以守护进程的方式启动的。因此需要在命令行参数中传递 --nodaemonize 禁止其以守护进程启动,否则上面使用 launchctl 来停止服务的操作就是无效的。

你还可以在 /etc/php-fpm.conf 中通过设置参数来禁用守护进程(命令行参数的优先级最高):

1; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
2; Default Value: yes
3daemonize = no

当然,最简单粗暴的重启办法是这样的,怎么都有效:

1sudo pkill php-fpm

参考

全文完