使用 nvm 和 pm2 的错误 运行 遗留 node.js 应用程序
Error running legacy node.js app with nvm and pm2
我的问题
我有一个 old nodejs 应用程序(运行s 在 v0.8.18
下!)我想保留 运行ning历史原因。我通常可以从命令行 运行 它(即 $ node app
),但我不能通过 pm2 运行 它(即 $ pm2 start app
)。
这是我的设置:
- Ubuntu 16.04
- 使用
nvm
- 节点
v0.8.18
为 运行 安装旧版应用
- node
v9.3.0
全局安装 pm2
的最新稳定版本
- 应用程序通过 nginx 反向代理(大致遵循 these instructions)
- 我在创建 following this thread 的应用程序的根文件夹中有一个配置文件
pm2.json
,如下所示:
[{
"name": "my-old-app",
"exec_interpreter": "node@0.8.18",
"script": "app.js",
"error": "error.log"
}]
- 用以下方式启动 pm2:
$ NVM_DIR=/home/myusername/.nvm/ pm2 start pm2.json
产量:
$ NVM_DIR=/home/myusername/.nvm/ pm2 start pm2.json
[PM2][WARN] Applications my-old-app not running, starting...
[PM2] Setting Node to v0.8.18 (path=/home/myusername/.nvm/v0.8.18/bin/node)
[PM2] App [my-old-app] launched (1 instances)
┌─────────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬────────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├─────────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼────────────┼──────────┤
│ my-old-app │ 0 │ fork │ 5879 │ online │ 0 │ 0s │ 0% │ 7.9 MB │ myusername │ disabled │
└─────────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
当我开始尝试以这种方式启动应用程序时,这是 运行ning pm2 show my-old-app
的结果
Describing process with id 0 - name my-old-app
┌───────────────────┬──────────────────────────────────────────────────┐
│ status │ errored │
│ name │ my-old-app │
│ restarts │ 15 │
│ uptime │ 0 │
│ script path │ /home/myusername/my-old-app/app.js │
│ script args │ N/A │
│ error log path │ /home/myusername/my-old-app/error-0.log │
│ out log path │ /home/myusername/.pm2/logs/my-old-app-out-0.log │
│ pid path │ /home/myusername/.pm2/pids/my-old-app-0.pid │
│ interpreter │ /home/myusername/.nvm/v0.8.18/bin/node │
│ interpreter args │ N/A │
│ script id │ 0 │
│ exec cwd │ /home/myusername/my-old-app/ │
│ exec mode │ fork_mode │
│ node.js version │ N/A │
│ watch & reload │ ✘ │
│ unstable restarts │ 0 │
│ created at │ N/A │
└───────────────────┴──────────────────────────────────────────────────┘
此外,error-0.log
中反复出现的错误是:
domain.js:66
throw er;
^
TypeError: Object #<Object> has no method 'unref'
at Object.PMX.init (/home/myusername/.nvm/versions/node/v9.3.0/lib/node_modules/pm2/node_modules/pmx/lib/pmx.js:81:8)
at Object.<anonymous> (/home/myusername/.nvm/versions/node/v9.3.0/lib/node_modules/pm2/lib/ProcessContainerFork.js:8:18)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.runMain (module.js:492:10)
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
I don't know why this doesn't work.
什么有效
如果我只是 运行 从命令行正常运行应用程序,它会按预期完美运行,即
$ nvm use 0.8.18
Now using node v0.8.18 (npm v1.2.2)
$ node app
info - socket.io started
Express server listening on port 37426
它通过 nginx 进行反向代理,并可通过 https://old.example.com 在浏览器中使用。仅供参考,我的 nginx 站点配置的内容:
server {
listen 80;
listen [::]:80;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/old.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/old.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf;
server_name old.example.com;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
# Pass requests for / to localhost:37426:
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:37426/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
显然,我不能只使用此设置,因为如果进程因任何原因中断,它不会重新启动。有任何想法吗?我尝试 运行 将应用程序与节点 v9.3.0
连接起来,但代码太旧了。它也太广泛了,无法以更新的形式重写。
从错误日志来看,您似乎正在尝试 运行 使用节点 v9.3.0
的应用程序。
将你的命令修改成这样[未测试]
NVM_DIR=/home/myusername/.nvm/ nvm use 0.8.18 && pm2 start pm2.json
我明白了。 pm2
depends upon pmx
, which in turn uses the setTimeout().unref()
function。 unref()
函数直到 v0.9.1
才被添加到 nodejs 中。由于我试图 运行 我的应用程序与节点 v0.8.18
,unref()
函数未定义因此出现 Object #<Object> has no method 'unref'
错误消息。
尝试 运行 我的应用程序在较新的节点版本下总是失败,但最终我意识到它总是因为同一个包而失败:bcrypt
。事实证明,这个包的原始作者使用了一个奇怪的、有问题的中间版本 bcrypt
(v0.7.5
)。当我将其切换到稍新的 bcrypt
(v0.7.6
) 时,我能够 运行 具有节点 v0.9.12
的整个应用程序,这反过来又使其安全pm2
使用 unref()
.
总结...
- 不要尝试使用
pm2
尝试 运行 节点应用程序 <v0.9.1
,或
- 如果这样做,您可能需要修改应用程序,使其可以 运行 与节点
>=v0.9.1
更新
pm2
的维护者之一让我知道 they don't officially support any versions of nodejs <v0.12
and soon they'll be dropping support for that as well。
我的问题
我有一个 old nodejs 应用程序(运行s 在 v0.8.18
下!)我想保留 运行ning历史原因。我通常可以从命令行 运行 它(即 $ node app
),但我不能通过 pm2 运行 它(即 $ pm2 start app
)。
这是我的设置:
- Ubuntu 16.04
- 使用
nvm
- 节点
v0.8.18
为 运行 安装旧版应用 - node
v9.3.0
全局安装pm2
的最新稳定版本
- 节点
- 应用程序通过 nginx 反向代理(大致遵循 these instructions)
- 我在创建 following this thread 的应用程序的根文件夹中有一个配置文件
pm2.json
,如下所示:
[{
"name": "my-old-app",
"exec_interpreter": "node@0.8.18",
"script": "app.js",
"error": "error.log"
}]
- 用以下方式启动 pm2:
$ NVM_DIR=/home/myusername/.nvm/ pm2 start pm2.json
产量:
$ NVM_DIR=/home/myusername/.nvm/ pm2 start pm2.json
[PM2][WARN] Applications my-old-app not running, starting...
[PM2] Setting Node to v0.8.18 (path=/home/myusername/.nvm/v0.8.18/bin/node)
[PM2] App [my-old-app] launched (1 instances)
┌─────────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬────────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├─────────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼────────────┼──────────┤
│ my-old-app │ 0 │ fork │ 5879 │ online │ 0 │ 0s │ 0% │ 7.9 MB │ myusername │ disabled │
└─────────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
当我开始尝试以这种方式启动应用程序时,这是 运行ning pm2 show my-old-app
Describing process with id 0 - name my-old-app
┌───────────────────┬──────────────────────────────────────────────────┐
│ status │ errored │
│ name │ my-old-app │
│ restarts │ 15 │
│ uptime │ 0 │
│ script path │ /home/myusername/my-old-app/app.js │
│ script args │ N/A │
│ error log path │ /home/myusername/my-old-app/error-0.log │
│ out log path │ /home/myusername/.pm2/logs/my-old-app-out-0.log │
│ pid path │ /home/myusername/.pm2/pids/my-old-app-0.pid │
│ interpreter │ /home/myusername/.nvm/v0.8.18/bin/node │
│ interpreter args │ N/A │
│ script id │ 0 │
│ exec cwd │ /home/myusername/my-old-app/ │
│ exec mode │ fork_mode │
│ node.js version │ N/A │
│ watch & reload │ ✘ │
│ unstable restarts │ 0 │
│ created at │ N/A │
└───────────────────┴──────────────────────────────────────────────────┘
此外,error-0.log
中反复出现的错误是:
domain.js:66
throw er;
^
TypeError: Object #<Object> has no method 'unref'
at Object.PMX.init (/home/myusername/.nvm/versions/node/v9.3.0/lib/node_modules/pm2/node_modules/pmx/lib/pmx.js:81:8)
at Object.<anonymous> (/home/myusername/.nvm/versions/node/v9.3.0/lib/node_modules/pm2/lib/ProcessContainerFork.js:8:18)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.runMain (module.js:492:10)
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
I don't know why this doesn't work.
什么有效
如果我只是 运行 从命令行正常运行应用程序,它会按预期完美运行,即
$ nvm use 0.8.18
Now using node v0.8.18 (npm v1.2.2)
$ node app
info - socket.io started
Express server listening on port 37426
它通过 nginx 进行反向代理,并可通过 https://old.example.com 在浏览器中使用。仅供参考,我的 nginx 站点配置的内容:
server {
listen 80;
listen [::]:80;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/old.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/old.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf;
server_name old.example.com;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
# Pass requests for / to localhost:37426:
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:37426/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
显然,我不能只使用此设置,因为如果进程因任何原因中断,它不会重新启动。有任何想法吗?我尝试 运行 将应用程序与节点 v9.3.0
连接起来,但代码太旧了。它也太广泛了,无法以更新的形式重写。
从错误日志来看,您似乎正在尝试 运行 使用节点 v9.3.0
的应用程序。
将你的命令修改成这样[未测试]
NVM_DIR=/home/myusername/.nvm/ nvm use 0.8.18 && pm2 start pm2.json
我明白了。 pm2
depends upon pmx
, which in turn uses the setTimeout().unref()
function。 unref()
函数直到 v0.9.1
才被添加到 nodejs 中。由于我试图 运行 我的应用程序与节点 v0.8.18
,unref()
函数未定义因此出现 Object #<Object> has no method 'unref'
错误消息。
尝试 运行 我的应用程序在较新的节点版本下总是失败,但最终我意识到它总是因为同一个包而失败:bcrypt
。事实证明,这个包的原始作者使用了一个奇怪的、有问题的中间版本 bcrypt
(v0.7.5
)。当我将其切换到稍新的 bcrypt
(v0.7.6
) 时,我能够 运行 具有节点 v0.9.12
的整个应用程序,这反过来又使其安全pm2
使用 unref()
.
总结...
- 不要尝试使用
pm2
尝试 运行 节点应用程序<v0.9.1
,或 - 如果这样做,您可能需要修改应用程序,使其可以 运行 与节点
>=v0.9.1
更新
pm2
的维护者之一让我知道 they don't officially support any versions of nodejs <v0.12
and soon they'll be dropping support for that as well。