Node.js 与 PHP 在 Linux 服务器上共存协作需注意权限隔离、进程管理与环境适配:PHP-FPM 应为站点配置独立用户并匹配 Nginx socket 权限;Node.js 需用非特权用户启动且限制子进程超时;CLI 调用 PHP 必须使用绝对路径并避免复用 Web 入口;PM2 与 systemd 不应混管,需统一 umask 避免文件权限冲突。

Node.js 和 PHP 本身不直接“连接”,所谓“Node.js 连 PHP”通常指两者共存于同一 Linux 服务器时的协作场景:比如 Node.js 做网关或实时服务,PHP 处理传统 Web 请求(如 WordPress、Laravel);或通过 child_process.exec、HTTP 调用、Unix socket 等方式让 Node.js 主动调用 PHP 脚本。稳定性不取决于“谁连谁”,而取决于权限隔离是否合理、进程生命周期是否可控。
PHP-FPM 与 Node.js 共用 Nginx 时的用户权限冲突
常见错误是 PHP-FPM 和 Node.js 都以 root 或同一低权限用户(如 www-data)运行,导致文件写入混乱、缓存污染、甚至 502 Bad Gateway。
- PHP-FPM 推荐为每个站点配置独立
user和group(如php-user1),并在www.conf中设置listen.owner和listen.group匹配 Nginx 用户 - Node.js 进程应使用非特权用户启动(如
node-app),且该用户对静态资源目录只有r-x权限,对日志目录有rw- - Nginx 的
user指令必须与 PHP-FPM 的listen.owner一致,否则 socket 文件权限拒绝访问 —— 错误日志中会出现connect() to unix:/run/php/php8.1-fpm.sock failed (13: Permission denied)
child_process.exec 调用 PHP 脚本的路径与环境陷阱
在 Node.js 中用 child_process.exec 执行 php /path/to/script.php 很容易失败,不是语法问题,而是环境缺失。
- PHP CLI 可能未安装(Ubuntu 默认只装
php-fpm),需显式安装php-cli包 - Node.js 进程的
PATH环境变量通常不含/usr/bin或/usr/local/bin,建议写绝对路径:/usr/bin/php /var/www/app/cli.php - PHP 脚本若依赖
$_SERVER或getenv(),CLI 模式下这些变量为空 —— 不要直接复用 Web 入口脚本,应单独写 CLI 入口,用$argv传参 - 超时必须设限:
{ timeout: 5000 },否则卡住的 PHP 进程会堆积,ps aux | grep php能看到大量defunct进程
进程守护与信号处理差异:PM2 vs systemd
Node.js 常用 PM2,PHP-FPM 由 systemd 管理,两者对 SIGHUP、SIGTERM 的响应逻辑不同,混用时易引发服务中断。
立即学习“PHP免费学习笔记(深入)”;
- 不要用 PM2 启动 PHP-FPM —— 它不是 Node.js 应用,PM2 无法正确捕获其子进程和日志
- Node.js 若监听
0.0.0.0:3000,需确保该端口未被 PHP-FPM 的status页面或其他服务占用(检查ss -tuln | grep :3000) - systemd 的
Restart=on-failure对 PHP-FPM 有效,但对 Node.js + PM2 是冗余的 —— 此时应关闭 PM2 的--watch,改用 systemd 直接管理node app.js,避免双重守护导致 PID 冲突 - PHP-FPM 的
pm.max_children和 Node.js 的集群模式(cluster模块)不能简单按 CPU 核数等比配置 —— 前者吃内存,后者吃事件循环负载,需分别压测
最常被忽略的是工作目录(cwd)和 umask:Node.js 子进程默认继承父进程的 umask,而 PHP-FPM 默认是 002,这会导致 Node.js 创建的文件 PHP 无法读取(尤其缓存或上传临时文件)。统一在启动脚本里加 process.umask(0o002),或在 systemd unit 文件中设置 UMask=0002。











