# Windows 上 Nginx + PHP FastCGI：没有 php-fpm，别幻想

> 把 php-cgi 作为 FastCGI 监听器，配置 Nginx 的 SCRIPT_FILENAME 与 fix_pathinfo，并理解为什么 IIS FastCGI 往往更适合 Windows。

**测试环境**

- 版本号: 26100.33650
- 版本: Standard / Datacenter
- 架构: x64
- 证据: E1
- 核验日期: 2026-10-29

## 一句话结论

Nginx **不会**自己拉起 PHP 工作进程。Windows 上你先启动 `php-cgi.exe` 作为 FastCGI 监听器，再让 Nginx 指过去：

```bat
C:\PHP\8.4\php-cgi.exe -b 127.0.0.1:9000 -c C:\PHP\8.4\php.ini
```

然后：

```nginx
location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;
}
```

Windows 没有官方 php-fpm。指南让你在 Windows 装 php-fpm，要么是第三方构建，要么把 FastCGI 和 FPM 混了。

## 完整 server 块

```nginx
server {
    listen 8084;
    server_name php.local;
    root C:/sites/php;
    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS $https if_not_empty;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_read_timeout 60s;
    }
}
```

`SCRIPT_FILENAME` 是最容易漏的参数。没有它，PHP-CGI 报 “No input file specified” 或空白页。

## 这种模式的 php.ini

```ini
cgi.fix_pathinfo=0
fastcgi.impersonate=1
date.timezone=UTC
expose_php=Off
display_errors=Off
log_errors=On
```

`cgi.fix_pathinfo=0` 加 `try_files`/`=404`，可以避免不存在的 `.php` 路径被交给 PHP-CGI。它不是上传校验的替代。

## 进程守护

PHP-CGI 是要你保活的进程：

- 用 WinSW/NSSM 或带重启的计划任务；
- 设 `PHP_FCGI_MAX_REQUESTS`（如 500）让 worker 回收；
- stderr/stdout 日志放在 Web 根之外；
- 监控监听器（`Test-NetConnection 127.0.0.1 9000`）；
- 不要在同一 9000 启动第二个监听器。

纯 Windows 服务器，**IIS FastCGI** 通常比手包 `php-cgi` 更能管好 PHP；已经标准化 Nginx 或需要它的配置模型时，再用 Nginx+PHP。

## 验证

```powershell
& C:\PHP\8.4\php-cgi.exe -v
Test-NetConnection 127.0.0.1 -Port 9000
Set-Content C:\sites\php\info.php '<?php phpinfo();' -Encoding ASCII
curl.exe -I -H "Host: php.local" http://127.0.0.1:8084/info.php
```

测完删 `info.php`。

> **警告: FastCGI 不是每请求 CGI**
>
> 一个 `php-cgi -b` 监听器处理多个请求。每请求起一个进程是旧 CGI 模型，负载一上来就崩。用守护器，并有意识地回收。

## 实验室边界

Nginx+PHP 为 E1。实验室装了 PHP 8.4.27 并验证 IIS FastCGI，但没有把 php-cgi 放到 Nginx 后面。Nginx 配置是下一步验证，不是已复现声明。

## 来源

- [nginx — FastCGI 模块](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
- [PHP 手册 — FastCGI Process Manager](https://www.php.net/manual/zh/install.fpm.php)
- [PHP — Windows 下载](https://windows.php.net/downloads/releases/)

---

来源页面: https://winbook.fyi/zh/server/web/nginx-php/
