使用PM2部署NextJS(NodeJS)应用时遇pipefail语法错误
问题背景
使用pm2部署NextJS构建的Node.js应用时,执行pm2 start后短暂显示应用在线,但pm2 list显示进程处于errored状态,已重启15次。查看pm2日志发现报错:
SyntaxError: Unexpected identifier 'pipefail' at Object.compileFunction (node:vm:360:18) at wrapSafe (node:internal/modules/cjs/loader:1088:15) at Module._compile (node:internal/modules/cjs/loader:1123:27) at Module._extensions..js (node:internal/modules/cjs/loader:1213:10) at Module.load (node:internal/modules/cjs/loader:1037:32) at Module._load (node:internal/modules/cjs/loader:878:12) at Object.<anonymous> (/home/equitica/.npm/_npx/5f7878ce38f1eb13/node_modules/pm2/lib/ProcessContainerFork.js:33:23) at Module._compile (node:internal/modules/cjs/loader:1159:14) at Module._extensions..js (node:internal/modules/cjs/loader:1213:10) at Module.load (node:internal/modules/cjs/loader:1037:32) /home/<username>/.asdf/plugins/nodejs/shims/npm:4 set -o pipefail ^^^^^^^^
错误指向/home/<username>/.asdf/plugins/nodejs/shims/npm文件中的set -o pipefail行。
先解释set -o pipefail的作用
这是Bash shell的一个配置选项:默认情况下,管道命令(比如cmd1 | cmd2)的退出状态只取最后一个命令的执行结果,开启pipefail后,只要管道中任意一个命令执行失败,整个管道的退出状态就会标记为失败,用于更严格的错误检查。
问题原因
pm2在fork模式下,错误地将asdf生成的npm Bash脚本当成Node.js脚本解析执行了,而Node.js无法识别Bash的语法,因此抛出pipefail标识符错误。
解决步骤
1. 修正pm2启动配置(推荐)
确保pm2直接启动NextJS的Node入口文件,而不是通过npm shim。比如在ecosystem.config.js中配置:
module.exports = { apps: [ { name: "your-app-name", script: "./.next/standalone/server.js", // NextJS独立构建后的入口文件 env: { NODE_ENV: "production", PORT: 3000 } } ] };
如果必须使用npm命令启动,需要指定pm2用bash作为解释器:
module.exports = { apps: [ { name: "your-app-name", script: "npm", args: "start", interpreter: "bash", // 关键:让pm2用bash执行npm命令 env: { NODE_ENV: "production" } } ] };
2. 临时应急方案(不推荐)
如果暂时无法修改pm2配置,可以注释掉asdf npm shim中的set -o pipefail行:
打开/home/<username>/.asdf/plugins/nodejs/shims/npm,将set -o pipefail改为# set -o pipefail,但这会降低asdf npm的错误检查能力,仅作为临时过渡方案。
3. 验证修复
修改配置后,执行以下命令重启pm2:
pm2 delete all pm2 start ecosystem.config.js pm2 list
确认进程状态为online,且没有重启次数异常。
内容的提问来源于stack exchange,提问作者Ade Indriawan

