从NodeJS调用PHP-CGI始终返回404错误
嘿,这个问题我之前帮人排查过好几次,核心原因是直接终端执行和CGI模式调用php-cgi的逻辑完全不一样——终端是直接让php-cgi处理指定脚本,而CGI模式需要完整的环境变量才能让它正确识别要执行的文件,缺了关键变量就会返回404。下面是一步步的排查和解决方法:
1. 必须添加SCRIPT_FILENAME环境变量
这是CGI模式下php-cgi找到目标脚本的核心变量!你当前的代码里完全没传这个,php-cgi根本不知道要执行哪个文件,直接返回404是必然的。
修改你的Node.js代码,把脚本路径通过环境变量传递,同时调整命令写法:
child_process.exec("php-cgi", { // 这里别再把脚本路径写在命令里了! env: { REQUEST_METHOD: method, CONTENT_LENGTH: body.length, QUERY_STRING: query, REDIRECT_STATUS: "200", // 这里要传字符串"200",不是布尔值true SCRIPT_FILENAME: "/home/user/test.php", // 关键!加上这个 DOCUMENT_ROOT: "/home/user" // 可选,但加上更符合CGI规范 } }, function (error, stdout, stderr) { // 你的后续处理逻辑 });
为什么要把脚本路径从命令移到环境变量?因为CGI模式下,php-cgi是通过SCRIPT_FILENAME来识别要执行的脚本,而不是命令行参数——终端执行是特殊的简化模式,和CGI调用逻辑不同。
2. 修正REDIRECT_STATUS的值
你之前传的是true,但这个变量要求是字符串类型的HTTP状态码(比如"200"),用来告诉php-cgi这是一个合法的CGI请求。传布尔值会导致它识别异常,也是可能触发404的原因。
3. 查看php-cgi的错误输出找线索
在你的回调函数里,一定要打印stderr的内容,php-cgi的错误提示都在这里:
function (error, stdout, stderr) { if (error) { console.error('执行出错:', error); } console.error('php-cgi错误日志:', stderr); // 重点看这个! console.log('php-cgi输出:', stdout); }
比如如果SCRIPT_FILENAME路径写错了,stderr里会明确提示“找不到脚本文件”,帮你快速定位问题。
4. 验证环境变量是否正确传递
可以在test.php里加一段代码,打印所有CGI环境变量,确认php-cgi有没有收到你传的参数:
<?php print_r($_SERVER); ?>
调用后查看stdout的输出,检查SCRIPT_FILENAME、REQUEST_METHOD这些变量是否和你设置的一致。如果没收到,可能是你在env里覆盖了系统默认环境——可以用Object.assign({}, process.env, { /* 你的自定义变量 */ })来合并系统环境和自定义变量,避免丢失必要的系统参数。
5. 检查PHP的cgi.fix_pathinfo配置
如果你的PHP配置里cgi.fix_pathinfo设为0,可能会导致php-cgi无法正确解析SCRIPT_FILENAME。可以在test.php里加一行echo ini_get('cgi.fix_pathinfo');看看值,如果是0,要么在php.ini里改成1,要么在脚本里临时设置:ini_set('cgi.fix_pathinfo', 1)。
内容的提问来源于stack exchange,提问作者Laef

