引言
在 2025 年 9 月 27 日的当前日期下,与一位用户进行了一次关于 Windows 批处理脚本的深入交流。该脚本旨在批量重装 PHP-CGI 服务,监听端口 9000~9004,但运行后部分服务无法启动。交流过程涉及问题诊断、脚本修改、端口冲突排查、乱码解决和意外服务删除,最终帮助用户优化脚本并清理环境。这篇文章整理了整个对话流程,旨在为类似问题提供参考,突出诊断逻辑和解决方案。
问题起源:脚本运行服务无法启动
用户最初分享了一个批处理脚本,用于使用 NSSM 工具重装 PHP-CGI 服务。脚本代码如下:
@echo off
REM === 一键重装 PHP-CGI 服务(9000~9004) ===
REM === 配置路径(按实际环境修改)===
set NSSM="D:\program\nssm\nssm.exe"
set PHP_CGI="D:\program\php\php-8.4.10-nts-Win32-vs17-x64\php-cgi.exe"
set BIND_IP=127.0.0.1
echo.
echo ================================
echo PHP-CGI 服务批量重装开始
echo ================================
for %%P in (9000 9001 9002 9003 9004) do (
echo.
echo [CHECK] 检查 php-cgi-%%P 是否存在...
sc query php-cgi-%%P >nul 2>&1
if %errorlevel%==0 (
echo [INFO] 停止 php-cgi-%%P ...
sc stop php-cgi-%%P >nul 2>&1
echo [INFO] 删除 php-cgi-%%P ...
%NSSM% remove php-cgi-%%P confirm
echo [OK] php-cgi-%%P 已卸载。
) else (
echo [SKIP] php-cgi-%%P 不存在,跳过卸载。
)
echo [INFO] 安装 php-cgi-%%P ...
%NSSM% install php-cgi-%%P %PHP_CGI% -b %BIND_IP%:%%P
if %errorlevel%==0 (
echo [OK] php-cgi-%%P 安装完成!
) else (
echo [ERROR] php-cgi-%%P 安装失败,请检查路径和权限!
)
)
echo.
echo ================================
echo 所有服务已处理完毕
echo 可用 sc start php-cgi-端口号 启动服务
echo ================================
pause
用户报告运行后某些服务无法启动。我分析了脚本,可能原因包括路径错误、权限不足、端口冲突、NSSM 版本过旧、php.ini 配置问题等。提供了优化后的脚本,增加了错误检查、等待逻辑和 php.ini 参数。
用户确认路径正确(NSSM 和 PHP-CGI 文件存在),但服务仍无法启动。我建议更新 NSSM 版本、检查 php.ini、端口占用,并提供了进一步的优化脚本。
排查端口冲突和 IIS 干扰
用户提供了端口占用输出:
TCP 0.0.0.0:9001 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:9002 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:9003 0.0.0.0:0 LISTENING 4
TCP 127.0.0.1:9000 0.0.0.0:0 LISTENING 11060
TCP 127.0.0.1:9004 0.0.0.0:0 LISTENING 9344
TCP [::]:9001 [::]:0 LISTENING 4
TCP [::]:9002 [::]:0 LISTENING 4
TCP [::]:9003 [::]:0 LISTENING 4
分析显示端口 9001~9003 被 PID 4 (System) 占用,这是 Windows HTTP.sys 驱动程序的特征,通常由 IIS 引起。我建议使用 netsh http show urlacl 检查和删除保留,使用 net stop http /y 停止 HTTP.sys 相关服务,并禁用 IIS 服务(如 sc config w3svc start= disabled)。
用户提供了 tasklist /svc | findstr "4" 输出,确认 IIS 相关进程(如 inetinfo.exe IISADMIN、w3wp.exe)存在。我进一步指导停止 IIS 服务,并提供了优化脚本。
用户反馈:“停止iis就可以启动了”,确认 IIS 占用是核心问题,服务成功启动。
服务删除和意外服务问题
用户随后询问如何删除 php-cgi-%%P 服务(一个意外创建的服务,状态为“暂停”)。我提供了手动删除步骤和专用删除脚本,使用 NSSM 或 sc delete。
用户报告运行脚本后出现乱码(如 'CK]' 不是内部或外部命令),并提供输出。我诊断为编码问题(脚本 UTF-8,CMD GBK),建议转换为 ANSI 编码,并提供了英文版脚本。
用户多次反馈 php-cgi-%%P 服务仍存在,我优化删除脚本,增加等待时间、强制终止进程和双重删除机制,并提供详细手动删除步骤。
用户要求将端口改为 9100~9104,我更新脚本,并强调以 .bat 文件运行以避免变量解析错误。
最终优化和总结
在交流过程中,我提供了多个脚本版本:
- 删除脚本(remove_php_cgi_pp.bat):专注于删除 php-cgi-%%P。
- 安装脚本(install_php_cgi.bat):批量重装服务,端口 9100~9104,包含日志配置和自动启动。
关键解决方案包括:
- 端口冲突:停止 IIS,删除 HTTP.sys 保留。
- 乱码:转换为 ANSI 编码,使用英文输出,设置 chcp 936。
- 意外服务:手动删除 php-cgi-%%P,脚本末尾检查清理。
- 脚本改进:添加权限检查、文件验证、残留进程清理。
用户问题最终解决,服务正常运行。这次交流突显了 Windows 服务管理中的常见坑点,如端口占用和编码兼容性。通过逐步诊断,用户获得了优化脚本和故障排除方法。
结语
这个调试过程展示了系统管理员在处理 Windows 脚本和服务时可能遇到的挑战。从初始脚本问题到最终优化,强调了权限、编码和进程管理的重完全要性。如果类似问题再次出现,建议先检查端口和事件日志,并以管理员身份运行脚本。这次交流不仅解决了具体问题,还提供了可复用的工具和知识。