简体   繁体   中英

Error running legacy node.js app with nvm and pm2

My Problem

I have an old nodejs app (runs under v0.8.18 !) that I'd like to keep running for historical reasons. I can run it normally from the command line (ie $ node app ), but I can't run it via pm2 (ie $ pm2 start app ).

Here's my setup:

  • Ubuntu 16.04
  • Using nvm
    • node v0.8.18 installed for running the legacy app
    • node v9.3.0 latest stable version with pm2 installed globally
  • App is reverse proxied through nginx (roughly following these instructions )
  • I have a config file pm2.json in the root folder of the app created following this thread that looks as follows:
[{
  "name": "my-old-app",
  "exec_interpreter": "node@0.8.18",
  "script": "app.js",
  "error": "error.log"
}]
  • Starting pm2 with:
$ NVM_DIR=/home/myusername/.nvm/ pm2 start pm2.json

yields:

$ 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

When I start try to start the app this way, here is the result of running 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                                              │
└───────────────────┴──────────────────────────────────────────────────┘

Furthermore, the error that shows up repeatedly in error-0.log is:

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.

What DOES Work

If I just run the app normally from the command line, it works perfectly as expected, ie

$ 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

It gets reverse proxied through nginx and is available in a browser via https://old.example.com . FYI, the contents of my nginx site config:

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;
  }
}

Clearly, I can't just use this setup because if the process is interrupted for any reason, it won't get restarted. Any ideas? I tried just running the app with node v9.3.0 but the code is too old. It's also too extensive to just re-write in more up-to-date form.

From the error log, it seems you are trying to run the app using node v9.3.0 .

modify your command into something like this [ not tested ]

NVM_DIR=/home/myusername/.nvm/ nvm use 0.8.18 && pm2 start pm2.json

I figured it out. pm2 depends upon pmx , which in turn uses the setTimeout().unref() function . The unref() function was not added to nodejs until v0.9.1 . Since I was trying to run my app with node v0.8.18 , the unref() function was undefined hence the Object #<Object> has no method 'unref' error message.

Trying to run my app under newer node versions always failed, but eventually I realized it was always failing because of the same package: bcrypt . It turns out the original authors of this package had used a weird, buggy, in-between version of bcrypt ( v0.7.5 ). When I switched it up to a slightly newer bcrypt ( v0.7.6 ), I was able to run the entire app with node v0.9.12 , which in turn, made it safe for pm2 to use unref() .

In Summary...

  1. Don't try to use pm2 to try to run node apps <v0.9.1 , or
  2. If you do, you'll likely need to modify the app so that it can be run with node >=v0.9.1

Update

One of the maintainers of pm2 let me know that they don't officially support any versions of nodejs <v0.12 and soon they'll be dropping support for that as well .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM