How to pass execution arguments to app using PM2?

105,670

Solution 1

You can do as stated in this ticket: https://github.com/Unitech/pm2/issues/13

Though if you're passing the environment you may want to consider leveraging environment variables. With this you create a variable which can be accessed by any process in that environment with process.env.*.

So you have a configuration file config.json:

{
   "dev": {
        "db": {
            "hosts":["localhost"],
            "database": "api"
        },
        "redis": {
            "hosts": ["localhost"]
        }
   },
   "staging": {
        "db": {
            "hosts":["1.1.1.1"],
            "database": "api"
        },
        "redis": {
            "hosts": ["2.2.2.2"]
        }
   },
   "production": {
        "db": {
            "hosts":["1.1.1.1", "1.1.1.2", "1.1.1.3"],
            "database": "api"
        },
        "redis": {
            "hosts": ["2.2.2.2", "2.2.2.3"]
        }
   }
}

Then you import your config:

var config=require('./config.json')[process.env.NODE_ENV || 'dev'];

db.connect(config.db.hosts, config.db.database);

Then you'd set the variable in your environment via shell:

export NODE_ENV=staging
pm2 start app.js

The environment variable will last as long as your session. So you'll have to set it in the ~/.bashrc file for that user for the variable to persist. This will set the variable every session.

PM2 has a deploy system which allows you to set an environment variable each time before your app is daemonized. This is how daemons in POSIX systems typically take parameters, because those parameters aren't lost with the process. Given with your circumstance it might not matter so much, but its a good practice.

Moreover you should consider stop/starting locally, and restarting(if in cluster mode) whenever possible to prevent downtime when in production.

Solution 2

If you want to pass node arguments from CLI then

pm2 start myServer.js --node-args="--production --port=1337"

.

Edited

you can add any arguments after --

pm2 start app.js -- --prod --second-arg --third-arg

Sails docs for deploymemt.

Solution 3

It is possible to define arguments with the process.

You can define a new process in ecosystem.config.js with an args key, like so:

{
  name            : 'my-service',
  script          : './src/service.js',
  args            : 'firstArg secondArg',
},
{
  name            : 'my-service-alternate',
  script          : './src/service.js',
  args            : 'altFirstArg altSecondArg',
}

Here, the two processes use the same file (service.js), but pass different arguments to it.

Note that these arguments are handled within service.js. In my case I just used process.argv[2] to get the first argument, and so on.

Solution 4

You can send arguments to your script by passing them after --. For example: pm2 start app.js -i max -- -a 23 // Pass arguments after -- to app.js

Solution 5

I have tested and it works in my windows machine. Below is the complete solution to pass arguments to nodejs app using pm2.

** There are also 2 types of argument

  1. node-args - to use before npm start
  2. args - to use in your node program

There are 2 ways to pass arguments with pm2.

Option 1: pass by argument with pm2 commands.

Option 2: by using config file e.g ecosystem.config.js

Option 1 (Pass arg by commands):

pm2 start app/myapp1.js --node-args="--max-http-header-size=80000" -- arg1 arg2
//Access the arg as below in your node program.
console.log(process.argv[2]); // arg1
console.log(process.argv[3]); // arg2

Option 2 (Using config file): If you are using ecosystem.config.js. you can define with the following configuration:

    {
      name: 'my-app',
      script: 'app\\myapp1.js',
      env: {
        NODE_ENV: 'DEV',
        PORT : 5051
      },
      node_args: '--max-http-header-size=80000',
      args : 'arg1 arg2',
      instances: 1,
      exec_mode: 'fork'
    }

To start as dev mode:

pm2 start --name myapp  app/myapp1.js -- .\ecosystem.config.js

To start as production mode, just add --env=production

pm2 start --name myapp  app/myapp1.js -- .\ecosystem.config.js --env=production 
//Access the arg as below in your node program.
console.log(process.argv[2]); // arg1
console.log(process.argv[3]); // arg2
Share:
105,670
user3373581
Author by

user3373581

Updated on July 08, 2022

Comments

  • user3373581
    user3373581 almost 2 years

    I am using pm2 to start my app but I'm not able to pass argument to it. The command I am using is pm2 start app.js -- dev. Though this works with forever.

  • Raj Rajen
    Raj Rajen over 8 years
    This is good. But when pass it to Docker, this is not working . Can anyone , pls help me. . ENTRYPOINT ["pm2"] CMD ["start", "msg/myServer.js", "--node-args='--firstarg'","--no-daemon"]
  • BuffMcBigHuge
    BuffMcBigHuge about 8 years
    I set this up with AWS Code Deploy and my Node.JS application, and it works wonderfully. I use port 4040 locally, and 80 on AWS. This is an elegant solution to ensure my ports are set up correctly. Thank you!
  • tsturzl
    tsturzl almost 8 years
    @RajRajen: If you're using docker I feel like running PM2 isn't your best option. Either let Docker monitor your app, and use its restart policy to keep your app alive, or use something like supervisord so your container doesn't have to restart every time your app goes down. When you run PM2 in docker you lose a lot of the useful features of PM2 and all it really does is keep your app alive. At that point using forever or an init system would do just as well, and probably be easier. Supervisord is extremely common for docker containers running more than 1 service per container.
  • Unitech
    Unitech about 7 years
    For docker you can use the dedicated PM2 command, pm2-docker. More informations here: pm2.keymetrics.io/docs/usage/docker-pm2-nodejs
  • Dave
    Dave over 6 years
    Just want to note that in the json config file, the field names are args and node-args
  • Nick Steele
    Nick Steele about 6 years
    Acording to pm2.keymetrics.io/docs/usage/quick-start you only need to add -- and anything after will be passed as arguments; there is no need for -x; -x means to execute a command using the fork system
  • Cameron Wilby
    Cameron Wilby almost 4 years
    Just adding that just because you can use PM2 in Docker doesn't mean you have to. Different use cases, different tools.
  • HankCa
    HankCa almost 4 years
    This is a better solution if you want ongoing (persistent) configuration. I think you missed the part about how to use ecosystem.config.js. Such as pm2 start ecosystem.config.js
  • xbmono
    xbmono about 3 years
    In your example you only set NODE_ENV to staging and db host for that is 1.1.1.1 but what if we don't know the db host until it goes to production, which is the case all the time. How do we set the db host at start up time? I'm still confused
  • tsturzl
    tsturzl about 3 years
    @xbmono I'd imagine you'd do some kind of service discovery, or read that via an env var. One trick is to make your config an actual js file and it can pull certain configs in from the environment or from discovery services(ie consul).
  • tsturzl
    tsturzl about 3 years
    @TobiasFeil That solution is noted in the link provided. Also providing configurations via env var and file is often better practice. I mentioned both solutions and chose to detail what I felt was the better solution. No need to be rude.
  • xbmono
    xbmono about 3 years
    Thanks @tsturzl - Yes that's what I need. Do you have any link that shows an example?
  • tsturzl
    tsturzl about 3 years
    @xbmono If you want to do service discovery that's highly dependent on your setup, whether you use something like consul, k8s, etc to provide service discovery, and that's hard to recommend without knowing a lot more. I made a really simple nodejs config example which pulls env vars into the config for example, do excuse my JS it's been years since I've worked with node so this might be outdated in some ways: gist.github.com/tsturzl/029d3863a3c2cdbc214a174d72c6ddb6
  • tsturzl
    tsturzl about 3 years
    @xbmono that example should show you how to pull in environment variables easily into the config itself. This is what I usually did when I was still working in nodejs, and I'd say this is pretty common.
  • Steve Tomlin
    Steve Tomlin about 3 years
    How can you pass an additional custom variable into this script?
  • Salim Shamim
    Salim Shamim almost 3 years
    When I run the first option it shows: error: unknown option --port