Pm2: Using different versions of node via nvm for each app

Created on 23 Feb 2015  路  38Comments  路  Source: Unitech/pm2

Here's the setup I'm thinking about.

All my apps run under ubuntu user app.
The pm2 startup script is configured with USER app.

app1 needs node 0.10
app2 needs node 0.12

I do the following

cd app1
nvm use 0.10
npm install -g pm2
pm2 start app.js --name "app1"

cd app2
nvm use 0.12
npm install -g pm2
pm2 start app.js --name "app2"

pm2 list lists both of the apps. If I inspect process.version in each of the apps - they're running the correct node version.

Is this a reasonable approach?

Question

Most helpful comment

It might. The only thing that nvm use 0.12 is doing is that it changes the node binary path so this will definitely work.

I think that changing the interpreter should work too (can't test right now):

$ pm2 start app.js --name app1 --interpreter=~/.nvm/versions/node/v0.12.0/bin/node

source

One of the advantage of this is that it can easily be reproduced in a json file:

[{
name: "app1",
exec_interpreter: "~/.nvm/versions/node/v0.11.0/bin/node"
},{
name: "app2",
exec_interpreter: "~/.nvm/versions/node/v0.12.0/bin/node"
}]

All 38 comments

It might. The only thing that nvm use 0.12 is doing is that it changes the node binary path so this will definitely work.

I think that changing the interpreter should work too (can't test right now):

$ pm2 start app.js --name app1 --interpreter=~/.nvm/versions/node/v0.12.0/bin/node

source

One of the advantage of this is that it can easily be reproduced in a json file:

[{
name: "app1",
exec_interpreter: "~/.nvm/versions/node/v0.11.0/bin/node"
},{
name: "app2",
exec_interpreter: "~/.nvm/versions/node/v0.12.0/bin/node"
}]

Works like a charm! The --interpreter option is neat since that way the option is persisted (or can be configured in the json file as you've mentioned).

Also the --interpreted way is better since I can always execute pm2 with node 0.12 and only use --interpreter to point to node 0.10 for the app. Whereas in my example above, I'm running pm2 commands with different version of node for each app (which is probably fine, but a bit weird).

Glad I helped.

It's not weird, pm2 is basically forking搂 your app, I don't know what clustering would be in this scenario.

搂 Just like you do in the shell node app.js #where node can be any binary you want.

Yeah, the forking makes sense.

But in my first example I'm running ~/.nvm/v0.10.36/bin/pm2 start app1 and then ~/.nvm/versions/node/v0.12.0/bin/pm2 app2 and later ~/.nvm/versions/node/v0.12.0/bin/pm2 list, etc. Basically I'm using 2 different versions of pm2 on 2 different versions of node to manage processes on 1 machine, that seems slightly risky since the 2 versions of pm2 might be different (depending on when I npm installed them) and there might be some incompatibilities between running them on node 0.10 and 0.12..

Which is why I prefer the --interpreter approach since I can always using the same pm2 for managing my processes.

Anyways, thanks for your help!

Has this been tested to correctly fork the right Node version during the pm2 startup process?

It does. At least in my setup where i start apps using a json manifest i.e. pm2 start app.json, where app.json contains the exec_interpereter option.

But cluster mode is not work.

I can second that. This is broken for cluster mode.
double checked.

nvm(ized) 6.2.0 node and 5.6.0 are my playpartners.

Tried the @soyuka method but is broken for me. app go to error without logs

It is now available with the latest PM2 version:

{ 
  apps : [{
    name : 'API',
    script : 'api.js',
    interpreter : '[email protected]'
 }]
}

https://github.com/Unitech/pm2/blob/master/test/fixtures/nvm-node-version/ecosystem.json#L12

This definitely works!

Thanks

I haven't got [email protected] to work with nvm. Where does pm2 looks for the nvm version of node? I also tried giving it an absolute path node /home/ubuntu/.nvm/vx.x.x/bin/node and was unsuccessful

@danielduhh See by yourself here, you the NVM_DIR to be defined in your path.

Does this work for cluster mode as well?

@geronime

PM2][WARN] Choosing the Node.js version in cluster mode is not supported

!!! TO ANYONE WHO FINDS THIS THREAD !!!
You need to give an absolute path to the --interpreter option (it does not resolve the ~)

EXAMPLE: --interpreter=/home/user/.nvm/v0.10.28/bin/node

You should just define the NVM_DIR and then use [email protected]

Thanks, can you show an example? And how it would work with NODE_ENV=

@GenericUK

NVM_DIR=/path/to/.nvm/ pm2 start pm2.json

pm2.json

[{
    "name": "app-name",
    "exec_interpreter": "[email protected]",
    "script": "server.js",
    "interpreter_args": "--harmony"
}]

Thanks, here's my startup for Ghost Blog Running PM2 in node current on NVM and older version of node for Ghost Blog. As it's running an a Raspberry Pi I've disabled logging to ease wear on the SD card.

NVM_DIR=~/.nvm NODE_ENV=development pm2 start ghost/index.js --name "GhostBlog" [email protected] -o "/dev/null" -e "/dev/null"

pm2 only work with nvm alias default
nvm use X && pm2 start doesn't use X node to run app
pass exec_interpreter is okay, but what if we need cluster mode ?

If I'm trying to run a _really_ old app (runs under Node v0.8.18!) in a time before pm2 existed, willpm2 still work?

If you use NVM you install PM2 under the latest Node then you can run your app in older Node using the interpreter argument (see my example above). You just need to make sure nvm current is latest node (the node version PM2 was installed under) when you run PM2

@GenericUK thanks. Yeah, that's what I tried first, but it hasn't been working, so I thought maybe it was because of how old my app was...

I figured it out! It turns out that the setTimeout().unref() function was not added until node v0.9.1 and since the pmx package used by pm2 uses the unref() function, I think it may not be possible to use pm2 to run node apps that require node <0.9.1.

In my particular case, it was the app's reliance on [email protected] that was causing the problem. I didn't write the original app, but eventually I figured out that using a different version of bcrypt would be perfectly satisfactory.

Do you think I should open up a separate issue to describe this particular situation?

@morphatic Sorry but we don't support node under 0.12 and soon we will also drop the support for 0.12

Am I wrong or --interpreter does not override ecosystem definition?
I think it should.

And can I pass x or + like [email protected] or node@8+?

--interpreter=<absolute nvm node binary path> is not working with ecosystem even when no interpreter or exec_interpreter is define inside that ecosystem.

PM2 just ignores the interpreter and looks for /usr/bin/node

I ran pm2 unstartup && pm2 startup, run my systemd command, started PM2 2.11.3 again and nothing happened

having NVM_DIR defined, i successfully ran pm2 start bin/www --name app_name --interpreter [email protected]

Is there any difference between interpreter and exec_interpreter?

@GenericUK

NVM_DIR=/path/to/.nvm/ pm2 start pm2.json

pm2.json

[{
  "name": "app-name",
  "exec_interpreter": "[email protected]",
  "script": "server.js",
  "interpreter_args": "--harmony"
}]

not work for me.

I don't know why pm2 still uses current node version instead of interpreter.

this is my case:
pm2's current node version: v10.23.0
program required node version: v8.17.0

ecosystem.json
{
"apps": [{
"name": "login-api",
"watch": [ "app.js", "config", "public" ],
"watch_options": {
"usePolling": true,
"followSymlinks": true
},
"interpreter": "[email protected]",
"exec_interpreter": "[email protected]",
"interpreter_args": "--harmony",
"instance_var": "INSTANCE_ID",
"env": {
"NODE_ENV": "production"
},
"exec_mode": "fork",
"cwd": "current",
"script": "./app.js",
"error_file": "../log/app-error.log",
"out_file": "../log/app-out.log"
}]
}

app-error.log

SyntaxError: Unexpected token import
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:617:28)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Function.Module.runMain (module.js:694:10)
at startup (bootstrap_node.js:204:16)
at bootstrap_node.js:625:3
/Users/CyrusNG/.nvm/versions/node/v10.23.0/lib/node_modules/pm2/lib/ProcessContainerFork.js:30
import(url.pathToFileURL(process.env.pm_exec_path));
^^^^^^

@CyrusNG have same error.

@shinebayar-g I am using [email protected]. And I tried following commands:
nvm use 8
pm2 update

then:
node@10's programs in pm2 will be from 'online' to 'errored' status
node@8's programs in pm2 will be from 'errored' to 'online' status

See this. https://github.com/Unitech/pm2/issues/4877 I think yours is same ?

import is experimental in node see https://nodejs.org/api/esm.html maybe that you want to use typescript or babel ? see https://pm2.io/docs/runtime/integration/transpilers/

I can confirm (different app/setup) that specifying the node version in the config file works for fork but not cluster at the moment.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexpts picture alexpts  路  3Comments

FujiHaruka picture FujiHaruka  路  3Comments

getvega picture getvega  路  3Comments

mario-mui picture mario-mui  路  3Comments

rangercyh picture rangercyh  路  4Comments