How to pass execution arguments to app using PM2? - node.js

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.

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.

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.

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.

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

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
node-args - to use before npm start
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

I always use PM2 to run my python scripts in Linux environment. So consider a script has a single parameter and needs to run continously after some amount if time, then we can pass it like this:
pm2 start <filename.py> --name <nameForJob> --interpreter <InterpreterName> --restart-delay <timeinMilliseconds> -- <param1> <param2>
filename.py is Name of the python script, without <> symbols, I want to run using PM2
nameForJob is the Meaningful name for the job, without <> symbols
InterpreterName is the python interpreter for running script, usually it is python3 in linux
timeinMilliseconds is the time our script needs to wait and re-run again
param1 is the first parameter for the script
param2 is the second parameter for the script.

Well there are 2 ways you can do to pass the parameters from pm2 to nodejs in CLI:
pm2 start app.js -- dev --port=1234 (note there is an extra space between -- and dev)
pm2 start app.js --node-args="dev --port=1234"
Both ways, you will find these values exist in process.argv (['dev','--port=1234'])

You can pass args for node just like that:
NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_ENV=dev pm2 start server.js --name web-server

I'll complement the answers above for npm scripts
For npm scripts
// package.json
{
"scripts": {
"start": "pm2 start --node-args=\"-r dotenv/config\" index.js"
}
}
npm run start runs pm2 start for index.js with node-args -r dotenv/config which include environment variables from .env file with dotenv

From the pm2 docs
//Inject what is declared in env_production
$ pm2 start app.js --env production
//Inject what is declared in env_staging
$ pm2 restart app.js --env staging

You need to start pm2 with something like:
pm2 start app.js --name "app_name" -- arg1 arg2
Then in your code, you can get your args with:
console.log(process.argv);
process.argv is a list like this:
[
'/usr/local/bin/node',
'/usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js',
'arg1',
'arg2'
]

Related

How to add node run option --max-http-header-size and add name to pm2 start command

How would I start a pm2 process with the —max-http-header-size node option, as well as name the process.
I have a server with multiple micro-services, one of the services is a web scraper.
This web scraper accepts requests with headers over the nodejs default 8kb limit. So, to run my app locally have to add the --max-http-header-size node option.
I've cloned my app to the server, but don't know how to set --max-http-header-size, nor do I know how to name the process within the pm2 start command.
So far my attempts have looked like this.
// this sets the name, but I don't know how to add the option `--max-http-header-size`
pm2 start npm --name "{REPONAME}" -- start
pm2 start node --name "scraper" --max-http-header-size 15000 app.js
pm2 start node --max-http-header-size 15000 app.js -- --name "scraper"
The accepted answer by David Harvey did not work for me as of Node 16. Instead, I had to use node_args, something like this:
{
"apps" : [{
"name" : "myapp",
"script" : "./app.js",
"node_args": "--max-http-header-size=256000",
"env": {
"NODE_ENV": "production",
}
}]
}
What you're looking for is called environment variables! You can pass environment variables to pm2 using a file that loads your server like this:
module.exports = {
apps : [
{
name: "myapp",
script: "./app.js",
watch: true,
node_args: "--max-http-header-size=16000"
}
]
}
Here's more about it too:
https://pm2.keymetrics.io/docs/usage/environment/

Node v15.5.0 doesn't read command line flags [duplicate]

The scripts portion of my package.json currently looks like this:
"scripts": {
"start": "node ./script.js server"
}
...which means I can run npm start to start the server. So far so good.
However, I would like to be able to run something like npm start 8080 and have the argument(s) passed to script.js (e.g. npm start 8080 => node ./script.js server 8080). Is this possible?
npm 2 and newer
It's possible to pass args to npm run since npm 2 (2014). The syntax is as follows:
npm run <command> [-- <args>]
Note the -- separator, used to separate the params passed to npm command itself, and the params passed to your script.
With the example package.json:
"scripts": {
"grunt": "grunt",
"server": "node server.js"
}
here's how to pass the params to those scripts:
npm run grunt -- task:target // invokes `grunt task:target`
npm run server -- --port=1337 // invokes `node server.js --port=1337`
Note: If your param does not start with - or --, then having an explicit -- separator is not needed; but it's better to do it anyway for clarity.
npm run grunt task:target // invokes `grunt task:target`
Note below the difference in behavior (test.js has console.log(process.argv)): the params which start with - or -- are passed to npm and not to the script, and are silently swallowed there.
$ npm run test foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', 'foobar']
$ npm run test -foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js']
$ npm run test --foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js']
$ npm run test -- foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', 'foobar']
$ npm run test -- -foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', '-foobar']
$ npm run test -- --foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', '--foobar']
The difference is clearer when you use a param actually used by npm:
$ npm test --help // this is disguised `npm --help test`
npm test [-- <args>]
aliases: tst, t
To get the parameter value, see this question. For reading named parameters, it's probably best to use a parsing library like yargs or minimist; nodejs exposes process.argv globally, containing command line parameter values, but this is a low-level API (whitespace-separated array of strings, as provided by the operating system to the node executable).
You asked to be able to run something like npm start 8080. This is possible without needing to modify script.js or configuration files as follows.
For example, in your "scripts" JSON value, include--
"start": "node ./script.js server $PORT"
And then from the command-line:
$ PORT=8080 npm start
I have confirmed that this works using bash and npm 1.4.23. Note that this work-around does not require GitHub npm issue #3494 to be resolved.
You could also do that:
In package.json:
"scripts": {
"cool": "./cool.js"
}
In cool.js:
console.log({ myVar: process.env.npm_config_myVar });
In CLI:
npm --myVar=something run-script cool
Should output:
{ myVar: 'something' }
Update: Using npm 3.10.3, it appears that it lowercases the process.env.npm_config_ variables? I'm also using better-npm-run, so I'm not sure if this is vanilla default behavior or not, but this answer is working. Instead of process.env.npm_config_myVar, try process.env.npm_config_myvar
jakub.g's answer is correct, however an example using grunt seems a bit complex.
So my simpler answer:
- Sending a command line argument to an npm script
Syntax for sending command line arguments to an npm script:
npm run [command] [-- <args>]
Imagine we have an npm start task in our package.json to kick off webpack dev server:
"scripts": {
"start": "webpack-dev-server --port 5000"
},
We run this from the command line with npm start
Now if we want to pass in a port to the npm script:
"scripts": {
"start": "webpack-dev-server --port process.env.port || 8080"
},
running this and passing the port e.g. 5000 via command line would be as follows:
npm start --port:5000
- Using package.json config:
As mentioned by jakub.g, you can alternatively set params in the config of your package.json
"config": {
"myPort": "5000"
}
"scripts": {
"start": "webpack-dev-server --port process.env.npm_package_config_myPort || 8080"
},
npm start will use the port specified in your config, or alternatively you can override it
npm config set myPackage:myPort 3000
- Setting a param in your npm script
An example of reading a variable set in your npm script. In this example NODE_ENV
"scripts": {
"start:prod": "NODE_ENV=prod node server.js",
"start:dev": "NODE_ENV=dev node server.js"
},
read NODE_ENV in server.js either prod or dev
var env = process.env.NODE_ENV || 'prod'
if(env === 'dev'){
var app = require("./serverDev.js");
} else {
var app = require("./serverProd.js");
}
As of npm 2.x, you can pass args into run-scripts by separating with --
Terminal
npm run-script start -- --foo=3
Package.json
"start": "node ./index.js"
Index.js
console.log('process.argv', process.argv);
I had been using this one-liner in the past, and after a bit of time away from Node.js had to try and rediscover it recently. Similar to the solution mentioned by #francoisrv, it utilizes the npm_config_* variables.
Create the following minimal package.json file:
{
"name": "argument",
"version": "1.0.0",
"scripts": {
"argument": "echo \"The value of --foo is '${npm_config_foo}'\""
}
}
Run the following command:
npm run argument --foo=bar
Observe the following output:
The value of --foo is 'bar'
All of this is nicely documented in the npm official documentation:
https://docs.npmjs.com/using-npm/config
Note: The Environment Variables heading explains that variables inside scripts do behave differently to what is defined in the documentation. This is true when it comes to case sensitivity, as well whether the argument is defined with a space or equals sign.
Note: If you are using an argument with hyphens, these will be replaced with underscores in the corresponding environment variable. For example, npm run example --foo-bar=baz would correspond to ${npm_config_foo_bar}.
Note: For non-WSL Windows users, see #Doctor Blue's comments below... TL;DR replace ${npm_config_foo} with %npm_config_foo%.
Use process.argv in your code then just provide a trailing $* to your scripts value entry.
As an example try it with a simple script which just logs the provided arguments to standard out echoargs.js:
console.log('arguments: ' + process.argv.slice(2));
package.json:
"scripts": {
"start": "node echoargs.js $*"
}
Examples:
> npm start 1 2 3
arguments: 1,2,3
process.argv[0] is the executable (node), process.argv[1] is your script.
Tested with npm v5.3.0 and node v8.4.0
Most of the answers above cover just passing the arguments into your NodeJS script, called by npm. My solution is for general use.
Just wrap the npm script with a shell interpreter (e.g. sh) call and pass the arguments as usual. The only exception is that the first argument number is 0.
For example, you want to add the npm script someprogram --env=<argument_1>, where someprogram just prints the value of the env argument:
package.json
"scripts": {
"command": "sh -c 'someprogram --env=$0'"
}
When you run it:
% npm run -s command my-environment
my-environment
If you want to pass arguments to the middle of an npm script, as opposed to just having them appended to the end, then inline environment variables seem to work nicely:
"scripts": {
"dev": "BABEL_ARGS=-w npm run build && cd lib/server && nodemon index.js",
"start": "npm run build && node lib/server/index.js",
"build": "mkdir -p lib && babel $BABEL_ARGS -s inline --stage 0 src -d lib",
},
Here, npm run dev passes the -w watch flag to babel, but npm run start just runs a regular build once.
For PowerShell users on Windows
The accepted answer did not work for me with npm 6.14. Neither adding no -- nor including it once does work. However, putting -- twice or putting "--" once before the arguments does the trick. Example:
npm run <my_script> -- -- <my arguments like --this>
Suspected reason
Like in bash, -- instructs PowerShell to treat all following arguments as literal strings, and not options (E.g see this answer). The issues seems to be that the command is interpreted one time more than expected, loosing the '--'. For instance, by doing
npm run <my_script> -- --option value
npm will run
<my_script> value
However, doing
npm run <my_script> "--" --option value
results in
<my_script> "--option" "value"
which works fine.
This doesn't really answer your question but you could always use environment variables instead:
"scripts": {
"start": "PORT=3000 node server.js"
}
Then in your server.js file:
var port = process.env.PORT || 3000;
I've found this question while I was trying to solve my issue with running sequelize seed:generate cli command:
node_modules/.bin/sequelize seed:generate --name=user
Let me get to the point. I wanted to have a short script command in my package.json file and to provide --name argument at the same time
The answer came after some experiments. Here is my command in package.json
"scripts: {
"seed:generate":"NODE_ENV=development node_modules/.bin/sequelize seed:generate"
}
... and here is an example of running it in terminal to generate a seed file for a user
> yarn seed:generate --name=user
> npm run seed:generate -- --name=user
FYI
yarn -v
1.6.0
npm -v
5.6.0
Note: This approach modifies your package.json on the fly, use it if you have no alternative.
I had to pass command line arguments to my scripts which were something like:
"scripts": {
"start": "npm run build && npm run watch",
"watch": "concurrently \"npm run watch-ts\" \"npm run watch-node\"",
...
}
So, this means I start my app with npm run start.
Now if I want to pass some arguments, I would start with maybe:
npm run start -- --config=someConfig
What this does is: npm run build && npm run watch -- --config=someConfig. Problem with this is, it always appends the arguments to the end of the script. This means all the chained scripts don't get these arguments(Args maybe or may not be required by all, but that's a different story.). Further when the linked scripts are called then those scripts won't get the passed arguments. i.e. The watch script won't get the passed arguments.
The production usage of my app is as an .exe, so passing the arguments in the exe works fine but if want to do this during development, it gets problamatic.
I couldn't find any proper way to achieve this, so this is what I have tried.
I have created a javascript file: start-script.js at the parent level of the application, I have a "default.package.json" and instead of maintaining "package.json", I maintain "default.package.json". The purpose of start-script.json is to read default.package.json, extract the scripts and look for npm run scriptname then append the passed arguments to these scripts. After this, it will create a new package.json and copy the data from default.package.json with modified scripts and then call npm run start.
const fs = require('fs');
const { spawn } = require('child_process');
// open default.package.json
const defaultPackage = fs.readFileSync('./default.package.json');
try {
const packageOb = JSON.parse(defaultPackage);
// loop over the scripts present in this object, edit them with flags
if ('scripts' in packageOb && process.argv.length > 2) {
const passedFlags = ` -- ${process.argv.slice(2).join(' ')}`;
// assuming the script names have words, : or -, modify the regex if required.
const regexPattern = /(npm run [\w:-]*)/g;
const scriptsWithFlags = Object.entries(packageOb.scripts).reduce((acc, [key, value]) => {
const patternMatches = value.match(regexPattern);
// loop over all the matched strings and attach the desired flags.
if (patternMatches) {
for (let eachMatchedPattern of patternMatches) {
const startIndex = value.indexOf(eachMatchedPattern);
const endIndex = startIndex + eachMatchedPattern.length;
// save the string which doen't fall in this matched pattern range.
value = value.slice(0, startIndex) + eachMatchedPattern + passedFlags + value.slice(endIndex);
}
}
acc[key] = value;
return acc;
}, {});
packageOb.scripts = scriptsWithFlags;
}
const modifiedJSON = JSON.stringify(packageOb, null, 4);
fs.writeFileSync('./package.json', modifiedJSON);
// now run your npm start script
let cmd = 'npm';
// check if this works in your OS
if (process.platform === 'win32') {
cmd = 'npm.cmd'; // https://github.com/nodejs/node/issues/3675
}
spawn(cmd, ['run', 'start'], { stdio: 'inherit' });
} catch(e) {
console.log('Error while parsing default.package.json', e);
}
Now, instead of doing npm run start, I do node start-script.js --c=somethis --r=somethingElse
The initial run looks fine, but haven't tested thoroughly. Use it, if you like for you app development.
I find it's possible to just pass variables exactly as you would to Node.js:
// index.js
console.log(process.env.TEST_ENV_VAR)
// package.json
...
"scripts": { "start": "node index.js" },
...
TEST_ENV_VAR=hello npm start
Prints out "hello"
From what I see, people use package.json scripts when they would like to run script in simpler way. For example, to use nodemon that installed in local node_modules, we can't call nodemon directly from the cli, but we can call it by using ./node_modules/nodemon/nodemon.js. So, to simplify this long typing, we can put this...
...
scripts: {
'start': 'nodemon app.js'
}
...
... then call npm start to use 'nodemon' which has app.js as the first argument.
What I'm trying to say, if you just want to start your server with the node command, I don't think you need to use scripts. Typing npm start or node app.js has the same effort.
But if you do want to use nodemon, and want to pass a dynamic argument, don't use script either. Try to use symlink instead.
For example using migration with sequelize. I create a symlink...
ln -s node_modules/sequelize/bin/sequelize sequelize
... And I can pass any arguement when I call it ...
./sequlize -h /* show help */
./sequelize -m /* upgrade migration */
./sequelize -m -u /* downgrade migration */
etc...
At this point, using symlink is the best way I could figure out, but I don't really think it's the best practice.
I also hope for your opinion to my answer.
Separate your arguments using -- from the script and add all the required arguments, we can later access them by index.
npm run start -- myemail#gmail.com 100
You can get params in node using
const params = process.argv.slice(2);
console.log(params);
Output
['myemail#gmail.com', '100']
I know there is an approved answer already, but I kinda like this JSON approach.
npm start '{"PROJECT_NAME_STR":"my amazing stuff", "CRAZY_ARR":[0,7,"hungry"], "MAGICAL_NUMBER_INT": 42, "THING_BOO":true}';
Usually I have like 1 var I need, such as a project name, so I find this quick n' simple.
Also I often have something like this in my package.json
"scripts": {
"start": "NODE_ENV=development node local.js"
}
And being greedy I want "all of it", NODE_ENV and the CMD line arg stuff.
You simply access these things like so in your file (in my case local.js)
console.log(process.env.NODE_ENV, starter_obj.CRAZY_ARR, starter_obj.PROJECT_NAME_STR, starter_obj.MAGICAL_NUMBER_INT, starter_obj.THING_BOO);
You just need to have this bit above it (I'm running v10.16.0 btw)
var starter_obj = JSON.parse(JSON.parse(process.env.npm_config_argv).remain[0]);
Anyhoo, question already answered. Thought I'd share, as I use this method a lot.
I settled for something like this, look at the test-watch script:
"scripts": {
"dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
"test": "tsc && cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest",
"test-watch": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 tsc-watch --onSuccess",
},
You invoke the test-watch script like this:
// Run all tests with odata in their name
npm run test-watch "jest odata"
npm run script_target -- < argument > Basically this is the way of passing the command line arguments but it will work only in case of when script have only one command running like I am running a command i.e. npm run start -- 4200
"script":{
"start" : "ng serve --port="
}
This will run for passing command line parameters but what if we run more then one command together like npm run build c:/workspace/file
"script":{
"build" : "copy c:/file <arg> && ng build"
}
but it will interpreter like this while running copy c:/file && ng build c:/work space/file
and we are expected something like this
copy c:/file c:/work space/file && ng build
Note :- so command line parameter only work ad expected in case of only one command in a script.
I read some answers above in which some of them are writing that you can access the command line parameter using $ symbol but this will not gonna work
Try cross-env NPM package.
Easy to use. Easy to install. Cross all platform.
Example:
set arguments for command
// package.json
"scripts": {
“test”: “node test.js”,
“test-with-env-arg”: “cross-env YourEnvVarName=strValue yarn test,
}
get arguments from process.env
// test.js
const getCommandLineArg = Boolean(process.env.YourEnvVarName === 'true') // Attention: value of process.env.* is String type, not number || boolean
i had the same issue when i need to deploy to different environments
here is the package.json pre and post the updates.
scripts:
{"deploy-sit": "sls deploy --config resources-sit.yml",
"deploy-uat": "sls deploy --config resources-uat.yml",
"deploy-dev": "sls deploy --config resources-dev.yml"}
but here is the correct method to adopt the environment variables rather than repeating ourselves
scripts:{"deploy-env": "sls deploy --config resources-$ENV_VAR.yml"}
finally you can deploy by running
ENV_VAR=dev npm run deploy-env

How can I check if my pm2 app NODE_ENV is getting set?

So I just deployed a site with node and pm2 for the first time and I'm going back and doing some optimization and reading best practices, etc.
I read that you can get a lot of benefit by setting NODE_ENV=production.
I found this in the pm2 docs:
[process.json]
"env_production" : {
"NODE_ENV": "production"
}
...
$ pm2 start process.json --env production
So, I did it but I have no idea if it is working. While trying to figure out how to check it I learned to try:
$ node
> process.env.NODE_ENV
> undefined
So, that's not a good sign.. but, with my limited understanding of how the low level stuff works, I can guess that maybe pm2 launches each app as a separate node process? So maybe I'm not in the right process when I try to check it.
Also, I don't know if I have to make a new ~/.pm2/dump.pm2 file because maybe whenever that is maybe overriding the options I set? (because I used pm2 startup).
How do I check if my pm2 app's NODE_ENV is set?
To answer the actual question in the title:
Within your script, for me my Express app's app.js file, you can use process.env.NODE_ENV to get the current value of NODE_ENV and log that out if you want.
An even better way is to use PM2's Process Metrics module, aka pmx.
yarn add pmx
or
npm install pmx --save
then
const Probe = require('pmx').probe()
Probe.metric({
name : 'NODE_ENV',
value : function() {
return process.env.NODE_ENV
}
})
Now it will show up in calls to pm2 monit (bottom left).
To change your environment:
It is necessary that you kill and restart the process to change your environment.
$ pm2 kill && pm2 start pm2.json --env production
The following isn't good enough:
pm2 restart pm2.json --env production
You can also check your NODE_ENV via running pm2 show <yourServerName>. This will output info about your running server including node env.
In addition, you can check your environment variables via running pm2 env 0. This will show all the environment variables for the running node process.
Start it with npm by adding this to your package.json:
"scripts": {
"myScript": "NODE_ENV=production pm2 start server.js"
}
Then
npm start myScript
You can do it directly too, but this is easy to manage, automate wth crontab and is in your source control...
Your process.json file is incomplete. Try using something like this:
[process.json]
{
"name" : "MyApp",
"script" : "myapp.js",
"env_production" : {
"NODE_ENV": "production"
}
}
Then add logging into your code, preferably somwhere on startup:
console.log("NODE_ENV : ", process.env.NODE_ENV);
Now start the application:
pm2 start process.json --env production
Lastly watch app logs:
pm2 logs MyApp
This should do it.
May be at the start of your server script you can print the value of the environment variable and then check the PM2 logs. Use the following code to print your environment variable value:
console.log('process.env.NODE_ENV:', process.env.NODE_ENV);
And then use the following code to see the PM2 logs
pm2 logs app_name
Here app_name is your process name as indicated by the entry in the process.json file.
You can set Environment variable for pm2 specifically.
go to /etc/systemd/system/ location.
you can see a file named pm2-username.service
file. (eg: pm2-root.service ) you can directly add an Enviorment variable for pm2.
for me, it was LD_LIBRARY_PATH . so I added the line as below after the PATH variable.
Environment=PATH=/usr/local/lib......
Environment=LD_LIBRARY_PATH=/opt/oracle/instantclient_21_1
after that, you can restart or start the node application with update-env flag,
pm2 start yourapp --update-env
try pm2 env <app_name/id> also you can find NODE_ENV in pm2 show <app_name/id>
In your terminal just type:
echo NODE_ENV
it will print current selected environment variable

Passing environment variables to node.js using pm2

I am trying to pass some arguments to my Express application which is run by pm2. There wasn't any hint in their documentation to do so, but apparently it's possible to pass some EV to your node application like SOME_STUFF=xxx pm2 start app.js.
Note - after updating environment variables in your environment, you must do the following:
pm2 restart all --update-env
ask me how I know...
Edit: also look for a .env file in the node source directory...
It's actually possible and I'm pretty sure it was in PM2's documentation some time ago.
Anyways, that's what you need to do:
pm2 start app.js -- -some_stuff xxx
Basically, add -- and then you can add your own app parameters.
Managed to find the source, it was hidden quite well: http://pm2.keymetrics.io/docs/usage/quick-start/#42-ways-of-starting-processes
I was having issues passing parameters using pm2 start app.js -- -some_stuff xxx so I opted to do this instead: SOME_STUFF=xxx OTHER_STUFF=abc pm2 start app.js.
Then when I ran pm2 logs I was able to see that my app successfully started and that the environment variables were set correctly where as before I was seeing errors around these variables when I ran pm2 logs.
The environment variables don't always update unless you force them to.
SOME_STUFF=xxx pm2 start app.js --update-env
You should pass ENV in ecosystem.config.js
ecosystem.config.js (in the root)
module.exports = {
apps: [
{
name: "project-name",
exec_mode: "cluster",
instances: "1",
script: "./server/index.js", // your script
args: "start",
env: {
NODE_ENV: "production",
SOME_ENV: "some_value"...
},
},
],
};
In the console:
pm2 start ecosystem.config.js
There is information about configuration of ENV in PM2 official documentation
My node app (sveltekit build) starts in my ubuntu server when I use
node build/index.js
and includes enviroment variables
so with pm2 I found that my app starts with envs starting it:
pm2 "node build/index.js"

Passing and Reading Parameters in PM2

I want to pass command line arguments to my script.
In forever I used to pass arguments like
forever start example.js 8080
I am unable to figure out how to do it in PM2.
I tried
pm2 start KratosReq.js -- -p 8080
but while reading from process.argv, the array contains
[ 'node', '/usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js' ]
Pm2 wrap your init script and fork node processes(cluster mode) , i think that is why you have that output , looking for declare enviroment variables in pm2 , you can use a json file to start up your server , or you can just start passing --node-args argument(checking pm2 help , there is that argument) , something like :
pm2 start KratosReq.js --node-args="-p=8080"
Hope this could help.

Resources