pm2启动Node脚本时全局安装的emailjs模块报MODULE_NOT_FOUND错误
PM2启动Node脚本时全局emailjs模块触发MODULE_NOT_FOUND的原因与解决
核心触发原因
- PM2守护进程不会自动继承当前用户登录Shell的自定义环境变量
你配置的NODE_PATH=/usr/lib/node_modules一般是写在用户级Shell配置文件(如.bashrc、.zshrc)中,只有在手动打开终端、进入Node REPL的场景下,Shell才会加载这些配置,让Node进程识别到全局模块的查找路径。而PM2本身是常驻后台的守护进程,不管是通过系统服务、开机自启还是后台方式启动,都不会主动读取用户目录下的Shell配置文件,也就拿不到你配置的NODE_PATH值,Node在PM2拉起的进程内执行require("emailjs/email")时,没有额外的路径指引,自然找不到对应的全局模块。 - Node的模块查找逻辑在无NODE_PATH时的默认行为
当NODE_PATH环境变量未生效时,Node的模块查找只会沿着脚本所在目录向上逐层检索node_modules目录,再匹配内置的固定全局模块路径,不会自动去你npm -g root输出的全局路径下查找第三方安装的包,因此会抛出Cannot find module的报错。
可落地的解决方式
- 启动PM2进程时显式注入NODE_PATH环境变量
手动启动时可以直接在命令行带环境变量参数执行:NODE_PATH=/usr/lib/node_modules pm2 start 你的脚本.js。如果使用PM2的配置文件管理进程,直接在配置文件的env配置项中加入NODE_PATH: "/usr/lib/node_modules"字段,重新加载进程即可让配置生效。 - 改用项目本地安装的依赖(最稳妥方案)
不依赖全局安装的包作为项目运行依赖,直接在项目根目录下执行本地安装命令:npm install emailjs --save,这样脚本的依赖会被安装到项目目录下的node_modules中,Node执行require时会自动检索到对应模块,完全不受环境变量配置、PM2加载逻辑的影响,从根源上避免这类路径找不到的问题。 - 全局托管PM2时配置系统级环境变量
如果PM2是通过systemd、开机自启等系统级方式托管运行,需要把NODE_PATH=/usr/lib/node_modules写到全局生效的环境变量配置文件(如/etc/environment)中,不要只依赖用户目录下的Shell配置,确保所有后台进程都能读取到这个变量值。
内容的提问来源于stack exchange,提问作者u936293
相关产品推荐
相关产品推荐

