From 4e5fd172813351240b999d1a71c4b453e2b24255 Mon Sep 17 00:00:00 2001 From: Michael Kalygin Date: Sat, 24 Aug 2024 17:53:09 +0400 Subject: [PATCH 1/5] test: add example with dotenvx to reproduce #3192 --update-env bug --- examples/dotenvx-pm2/.env | 4 ++++ examples/dotenvx-pm2/README.md | 8 +++++++ examples/dotenvx-pm2/ecosystem.config.cjs | 28 +++++++++++++++++++++++ examples/dotenvx-pm2/index.js | 27 ++++++++++++++++++++++ examples/dotenvx-pm2/package.json | 23 +++++++++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 examples/dotenvx-pm2/.env create mode 100644 examples/dotenvx-pm2/README.md create mode 100644 examples/dotenvx-pm2/ecosystem.config.cjs create mode 100644 examples/dotenvx-pm2/index.js create mode 100644 examples/dotenvx-pm2/package.json diff --git a/examples/dotenvx-pm2/.env b/examples/dotenvx-pm2/.env new file mode 100644 index 0000000000..28eead5fb0 --- /dev/null +++ b/examples/dotenvx-pm2/.env @@ -0,0 +1,4 @@ +DE=dotenv +SH_DE=dotenv +DE_PM=dotenv +SH_DE_PM=dotenv diff --git a/examples/dotenvx-pm2/README.md b/examples/dotenvx-pm2/README.md new file mode 100644 index 0000000000..b1da5a0106 --- /dev/null +++ b/examples/dotenvx-pm2/README.md @@ -0,0 +1,8 @@ + +To start http application in cluster mode: + +```bash +$ pm2 start ecosystem.config.js +# OR +$ pm2 start http.js -i max +``` diff --git a/examples/dotenvx-pm2/ecosystem.config.cjs b/examples/dotenvx-pm2/ecosystem.config.cjs new file mode 100644 index 0000000000..bcf4be1119 --- /dev/null +++ b/examples/dotenvx-pm2/ecosystem.config.cjs @@ -0,0 +1,28 @@ +module.exports = { + apps: [ + { + name: 'forked_app', + script: './index.js', + env: { + PORT: 8001, + PM: 'pm2', + SH_PM: 'pm2', + DE_PM: 'pm2', + SH_DE_PM: 'pm2', + }, + }, + { + name: 'clustered_app', + script: './index.js', + instances: 2, + exec_mode: 'cluster', + env: { + PORT: 8002, + PM: 'pm2', + SH_PM: 'pm2', + DE_PM: 'pm2', + SH_DE_PM: 'pm2', + }, + }, + ], +}; diff --git a/examples/dotenvx-pm2/index.js b/examples/dotenvx-pm2/index.js new file mode 100644 index 0000000000..589c4b73ca --- /dev/null +++ b/examples/dotenvx-pm2/index.js @@ -0,0 +1,27 @@ +import http from 'http'; + +const { + PORT, + SH, + DE, + PM, + SH_DE, + SH_PM, + DE_PM, + SH_DE_PM, +} = process.env; + +http.createServer((req, res) => { + res.writeHead(200); + res.end(JSON.stringify({ + SH, + DE, + PM, + SH_DE, + SH_PM, + DE_PM, + SH_DE_PM, + }, null, 2)); +}).listen(PORT, '0.0.0.0', () => { + console.log(`App listening on port ${PORT}`); +}); diff --git a/examples/dotenvx-pm2/package.json b/examples/dotenvx-pm2/package.json new file mode 100644 index 0000000000..e3eea666d6 --- /dev/null +++ b/examples/dotenvx-pm2/package.json @@ -0,0 +1,23 @@ +{ + "name": "dotenvx-pm2", + "version": "1.0.0", + "description": "Example usage of dotenvx with pm2", + "main": "index.js", + "type": "module", + "author": "Michael Kalygin", + "license": "MIT", + "scripts": { + "start:json:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 start ecosystem.config.cjs", + "start:json:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 start ecosystem.config.cjs", + "start:pid:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 start forked_app clustered_app", + "start:pid:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 start forked_app clustered_app", + "reload:json:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 reload ecosystem.config.cjs --update-env", + "reload:json:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 reload ecosystem.config.cjs --update-env", + "reload:pid:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 reload forked_app clustered_app --update-env", + "reload:pid:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 reload forked_app clustered_app --update-env", + "delete": "../../bin/pm2 delete ecosystem.config.cjs" + }, + "dependencies": { + "@dotenvx/dotenvx": "^1.10.2" + } +} From 38d7782b2d44d891e8ea27eb694bf111be4f4d69 Mon Sep 17 00:00:00 2001 From: Michael Kalygin Date: Sun, 25 Aug 2024 17:46:42 +0400 Subject: [PATCH 2/5] test: complete dotenvx example and add docs --- examples/dotenvx-pm2/.env | 4 --- examples/dotenvx-pm2/.env.initial | 4 +++ examples/dotenvx-pm2/.env.updated | 4 +++ examples/dotenvx-pm2/README.md | 21 +++++++++++--- examples/dotenvx-pm2/ecosystem.config.cjs | 34 ++++++++++++++++------- examples/dotenvx-pm2/package.json | 13 +++------ 6 files changed, 53 insertions(+), 27 deletions(-) delete mode 100644 examples/dotenvx-pm2/.env create mode 100644 examples/dotenvx-pm2/.env.initial create mode 100644 examples/dotenvx-pm2/.env.updated diff --git a/examples/dotenvx-pm2/.env b/examples/dotenvx-pm2/.env deleted file mode 100644 index 28eead5fb0..0000000000 --- a/examples/dotenvx-pm2/.env +++ /dev/null @@ -1,4 +0,0 @@ -DE=dotenv -SH_DE=dotenv -DE_PM=dotenv -SH_DE_PM=dotenv diff --git a/examples/dotenvx-pm2/.env.initial b/examples/dotenvx-pm2/.env.initial new file mode 100644 index 0000000000..315c7be05f --- /dev/null +++ b/examples/dotenvx-pm2/.env.initial @@ -0,0 +1,4 @@ +DE=dotenv_initial +SH_DE=dotenv_initial +DE_PM=dotenv_initial +SH_DE_PM=dotenv_initial diff --git a/examples/dotenvx-pm2/.env.updated b/examples/dotenvx-pm2/.env.updated new file mode 100644 index 0000000000..3689eaaac6 --- /dev/null +++ b/examples/dotenvx-pm2/.env.updated @@ -0,0 +1,4 @@ +DE=dotenv_updated +SH_DE=dotenv_updated +DE_PM=dotenv_updated +SH_DE_PM=dotenv_updated diff --git a/examples/dotenvx-pm2/README.md b/examples/dotenvx-pm2/README.md index b1da5a0106..6bf7fe2107 100644 --- a/examples/dotenvx-pm2/README.md +++ b/examples/dotenvx-pm2/README.md @@ -1,8 +1,21 @@ +This is an example of using [dotenvx](https://dotenvx.com/) with pm2. -To start http application in cluster mode: +It demonstrates how to update the environment for forked and clustered apps using dotenvx. + +In this example, the environment variables come from three sources and are applied in the following order (dotenv files take precedence because of the `--overload` option used): +- shell environment +- dotenv files `.env.initial` or `.env.updated`. +- pm2 ecosystem config `ecosystem.config.cjs` + +See `package.json` scripts for the actual commands. ```bash -$ pm2 start ecosystem.config.js -# OR -$ pm2 start http.js -i max +# install dotenvx +npm install +# start apps with `initial` environment and `.env.initial` dotenv file +npm run start:json +# reload apps with `updated` environment and `.env.updated` dotenv file +npm run reload:json +# delete apps +npm run delete:json ``` diff --git a/examples/dotenvx-pm2/ecosystem.config.cjs b/examples/dotenvx-pm2/ecosystem.config.cjs index bcf4be1119..c708322b64 100644 --- a/examples/dotenvx-pm2/ecosystem.config.cjs +++ b/examples/dotenvx-pm2/ecosystem.config.cjs @@ -3,12 +3,19 @@ module.exports = { { name: 'forked_app', script: './index.js', - env: { + env_initial: { PORT: 8001, - PM: 'pm2', - SH_PM: 'pm2', - DE_PM: 'pm2', - SH_DE_PM: 'pm2', + PM: 'pm2_initial', + SH_PM: 'pm2_initial', + DE_PM: 'pm2_initial', + SH_DE_PM: 'pm2_initial', + }, + env_updated: { + PORT: 8001, + PM: 'pm2_updated', + SH_PM: 'pm2_updated', + DE_PM: 'pm2_updated', + SH_DE_PM: 'pm2_updated', }, }, { @@ -16,12 +23,19 @@ module.exports = { script: './index.js', instances: 2, exec_mode: 'cluster', - env: { + env_initial: { + PORT: 8002, + PM: 'pm2_initial', + SH_PM: 'pm2_initial', + DE_PM: 'pm2_initial', + SH_DE_PM: 'pm2_initial', + }, + env_updated: { PORT: 8002, - PM: 'pm2', - SH_PM: 'pm2', - DE_PM: 'pm2', - SH_DE_PM: 'pm2', + PM: 'pm2_updated', + SH_PM: 'pm2_updated', + DE_PM: 'pm2_updated', + SH_DE_PM: 'pm2_updated', }, }, ], diff --git a/examples/dotenvx-pm2/package.json b/examples/dotenvx-pm2/package.json index e3eea666d6..99fc0d3fe2 100644 --- a/examples/dotenvx-pm2/package.json +++ b/examples/dotenvx-pm2/package.json @@ -7,15 +7,10 @@ "author": "Michael Kalygin", "license": "MIT", "scripts": { - "start:json:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 start ecosystem.config.cjs", - "start:json:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 start ecosystem.config.cjs", - "start:pid:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 start forked_app clustered_app", - "start:pid:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 start forked_app clustered_app", - "reload:json:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 reload ecosystem.config.cjs --update-env", - "reload:json:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 reload ecosystem.config.cjs --update-env", - "reload:pid:simple": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env -- ../../bin/pm2 reload forked_app clustered_app --update-env", - "reload:pid:overload": "SH=shell SH_DE=shell SH_PM=shell SH_DE_PM=shell dotenvx run --env-file .env --overload -- ../../bin/pm2 reload forked_app clustered_app --update-env", - "delete": "../../bin/pm2 delete ecosystem.config.cjs" + "start:json": "SH=shell_initial SH_DE=shell_initial SH_PM=shell_initial SH_DE_PM=shell_initial dotenvx run --env-file .env.initial --overload -- ../../bin/pm2 start ecosystem.config.cjs --env initial", + "reload:json": "SH=shell_updated SH_DE=shell_updated SH_PM=shell_updated SH_DE_PM=shell_updated dotenvx run --env-file .env.updated --overload -- ../../bin/pm2 reload ecosystem.config.cjs --env updated --update-env", + "delete:json": "../../bin/pm2 delete ecosystem.config.cjs", + "test:json": "../../bin/pm2 update && npm run delete:json && npm run start:json && npm run reload:json" }, "dependencies": { "@dotenvx/dotenvx": "^1.10.2" From 83ea16015368c7ea81ed0cdac6b0b6abc51456b3 Mon Sep 17 00:00:00 2001 From: Michael Kalygin Date: Sun, 25 Aug 2024 18:44:57 +0400 Subject: [PATCH 3/5] test: add unit tests for --update-env option --- test/programmatic/env_switching.js | 119 +++++++++++++++++++++++++++-- test/unit.sh | 0 2 files changed, 111 insertions(+), 8 deletions(-) mode change 100644 => 100755 test/unit.sh diff --git a/test/programmatic/env_switching.js b/test/programmatic/env_switching.js index fe55ce424e..39eaf3a621 100644 --- a/test/programmatic/env_switching.js +++ b/test/programmatic/env_switching.js @@ -130,14 +130,117 @@ describe('PM2 programmatic calls', function() { }); }); - // it('should start a script and NODE_ENV have right value', function(done) { - // pm2.start(json_declaration_simple, function(err, data) { - // proc1 = data[0]; - // should(err).be.null; - // proc1.pm2_env['NODE_ENV'].should.eql(json_declaration.env.NODE_ENV); - // done(); - // }); - // }); + /** + * Ensuring that environment update works correct when reloading with JSON config. + * + * Related issue: + * https://github.com/Unitech/pm2/issues/3192 + */ + describe('with updateEnv option', () => { + const env = { + shell: { + initial: { + SH: 'shell_initial', + SH_PM: 'shell_initial', + }, + updated: { + SH: 'shell_updated', + SH_PM: 'shell_updated', + }, + }, + pm2: { + initial: { + PM: 'pm2_initial', + SH_PM: 'pm2_initia', + }, + updated: { + PM: 'pm2_updated', + SH_PM: 'pm2_updated', + }, + }, + }; + + const configInitial = { + name: 'child-update-env', + script: './../fixtures/env-switching/child.js', + instances: '2', + env: { + NODE_ENV: 'test', + ...env.pm2.initial, + }, + }; + + const configUpdated = { + ...configInitial, + env: { + NODE_ENV: 'test', + ...env.pm2.updated, + }, + }; + + it('should inject shell environment, then inject config environment on start', (done) => { + Object.assign(process.env, env.shell.initial); + + pm2.start(configInitial, (err, data) => { + try { + const pm2Env = data[0] ? data[0].pm2_env || {} : {}; + should(err).be.null(); + should(pm2Env.SH).eql(env.shell.initial.SH); + should(pm2Env.PM).eql(env.pm2.initial.PM); + should(pm2Env.SH_PM).eql(env.pm2.initial.SH_PM); + done(); + } catch (err) { + done(err); + } + }); + }); + + it('should inject only config environment on restart when disabled', (done) => { + Object.assign(process.env, env.shell.updated); + + pm2.restart(configUpdated, { updateEnv: false }, (err) => { + should(err).be.null(); + + pm2.list((err, data) => { + try { + const pm2Env = data.find(proc => proc.name === configInitial.name).pm2_env; + should(err).be.null(); + should(pm2Env.SH).eql(env.shell.initial.SH); + should(pm2Env.PM).eql(env.pm2.updated.PM); + should(pm2Env.SH_PM).eql(env.pm2.updated.SH_PM); + done(); + } catch (err) { + done(err); + } + }); + }); + }); + it('should inject shell environment, then inject config environment on start when endabled', (done) => { + Object.assign(process.env, env.shell.updated); + + pm2.restart(configUpdated, { updateEnv: true }, (err) => { + should(err).be.null(); + + pm2.list((err, data) => { + try { + const pm2Env = data.find(proc => proc.name === configInitial.name).pm2_env; + should(err).be.null(); + should(pm2Env.SH).eql(env.shell.updated.SH); + should(pm2Env.PM).eql(env.pm2.updated.PM); + should(pm2Env.SH_PM).eql(env.pm2.updated.SH_PM); + done(); + } catch (err) { + done(err); + } + }); + }); + }); + it('should delete all processes', (done) => { + pm2.delete('all', (err, ret) => { + done(); + }); + }); + }); }); diff --git a/test/unit.sh b/test/unit.sh old mode 100644 new mode 100755 From 42341e74f6bdb924078d628069218fbcafc44a6e Mon Sep 17 00:00:00 2001 From: Michael Kalygin Date: Sun, 25 Aug 2024 19:16:38 +0400 Subject: [PATCH 4/5] test: add e2e tests for --update-env option --- test/e2e.sh | 0 test/e2e/cli/env-refresh.sh | 95 ++++++++++++++++++++++++++++++ test/fixtures/update-env.config.js | 22 +++++++ test/fixtures/update-env.js | 5 ++ test/programmatic/env_switching.js | 2 +- 5 files changed, 123 insertions(+), 1 deletion(-) mode change 100644 => 100755 test/e2e.sh create mode 100644 test/fixtures/update-env.config.js create mode 100644 test/fixtures/update-env.js diff --git a/test/e2e.sh b/test/e2e.sh old mode 100644 new mode 100755 diff --git a/test/e2e/cli/env-refresh.sh b/test/e2e/cli/env-refresh.sh index 418c9e2f5b..110f3d2c45 100644 --- a/test/e2e/cli/env-refresh.sh +++ b/test/e2e/cli/env-refresh.sh @@ -88,3 +88,98 @@ $pm2 kill $pm2 l NODE_PATH='/test2' $pm2 start local_require.js -i 1 should 'should have loaded the right globalPaths' 'restart_time: 0' 1 + +# +# Ensuring that environment update works correctly when reloading with JSON config. +# +# Related issue: +# https://github.com/Unitech/pm2/issues/3192 +# + +# start with config +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +>out-env.log + +sleep 0.5 +grep "SH=shell_initial PM=pm2_initial SH_PM=pm2_initial" out-env.log &> /dev/null +spec "should inject shell environment, then inject config environment on start with config" + +# restart config without --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 restart update-env.config.js --env updated +>out-env.log + +sleep 0.5 +grep "SH=shell_updated PM=pm2_updated SH_PM=pm2_updated" out-env.log &> /dev/null +spec "should inject shell environment, then inject config environment on restart with config and without --update-env option" + +# reload config without --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 reload update-env.config.js --env updated +>out-env.log + +sleep 0.5 +grep "SH=shell_updated PM=pm2_updated SH_PM=pm2_updated" out-env.log &> /dev/null +spec "should inject shell environment, then inject config environment on reload with config and without --update-env option" + +# restart config with --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 restart update-env.config.js --env updated --update-env +>out-env.log + +sleep 0.5 +grep "SH=shell_updated PM=pm2_updated SH_PM=pm2_updated" out-env.log &> /dev/null +spec "should inject shell environment, then inject config environment on restart with config and with --update-env option" + +# reload config with --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 reload update-env.config.js --env updated --update-env +>out-env.log + +sleep 0.5 +grep "SH=shell_updated PM=pm2_updated SH_PM=pm2_updated" out-env.log &> /dev/null +spec "should inject shell environment, then inject config environment on reload with config and with --update-env option" + +# restart pid without --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 restart update_env_app +>out-env.log + +sleep 0.5 +grep "SH=shell_initial PM=pm2_initial SH_PM=pm2_initial" out-env.log &> /dev/null +spec "should keep environment on restart with pid and without --update-env option" + +# reload pid without --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 reload update_env_app +>out-env.log + +sleep 0.5 +grep "SH=shell_initial PM=pm2_initial SH_PM=pm2_initial" out-env.log &> /dev/null +spec "should keep environment on reload with pid and without --update-env option" + +# restart pid with --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 restart update_env_app --update-env +>out-env.log + +sleep 0.5 +grep "SH=shell_updated PM=pm2_initial SH_PM=shell_updated" out-env.log &> /dev/null +spec "should inject shell environment on restart with pid and with --update-env option" + +# reload pid with --update-env +$pm2 delete all +SH=shell_initial SH_PM=shell_initial $pm2 start update-env.config.js --env initial +SH=shell_updated SH_PM=shell_updated $pm2 reload update_env_app --update-env +>out-env.log + +sleep 0.5 +grep "SH=shell_updated PM=pm2_initial SH_PM=shell_updated" out-env.log &> /dev/null +spec "should inject shell environment on reload with pid and with --update-env option" diff --git a/test/fixtures/update-env.config.js b/test/fixtures/update-env.config.js new file mode 100644 index 0000000000..550bdaf6f4 --- /dev/null +++ b/test/fixtures/update-env.config.js @@ -0,0 +1,22 @@ +module.exports = { + apps: [ + { + name: 'update_env_app', + script: './update-env.js', + instances: 2, + exec_mode: 'cluster', + out_file: 'out-env.log', + merge_logs: true, + env_initial: { + NODE_ENV: 'test', + PM: 'pm2_initial', + SH_PM: 'pm2_initial', + }, + env_updated: { + NODE_ENV: 'test', + PM: 'pm2_updated', + SH_PM: 'pm2_updated', + }, + }, + ], +}; diff --git a/test/fixtures/update-env.js b/test/fixtures/update-env.js new file mode 100644 index 0000000000..0654665b95 --- /dev/null +++ b/test/fixtures/update-env.js @@ -0,0 +1,5 @@ +setInterval(() => { + const { SH, PM, SH_PM } = process.env; + + console.log(`SH=${SH} PM=${PM} SH_PM=${SH_PM}`); +}, 100); diff --git a/test/programmatic/env_switching.js b/test/programmatic/env_switching.js index 39eaf3a621..da1a9d61fa 100644 --- a/test/programmatic/env_switching.js +++ b/test/programmatic/env_switching.js @@ -131,7 +131,7 @@ describe('PM2 programmatic calls', function() { }); /** - * Ensuring that environment update works correct when reloading with JSON config. + * Ensuring that environment update works correctly when reloading with JSON config. * * Related issue: * https://github.com/Unitech/pm2/issues/3192 From 304fc5e59706bd26dbd8c6660e6e1b505ceff487 Mon Sep 17 00:00:00 2001 From: Michael Kalygin Date: Sun, 25 Aug 2024 19:17:37 +0400 Subject: [PATCH 5/5] fix: reloading with --update-env option #3192 --- lib/API.js | 2 +- lib/Utility.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/API.js b/lib/API.js index 8b7bf2fa65..8a4ed1bdd7 100644 --- a/lib/API.js +++ b/lib/API.js @@ -1071,7 +1071,7 @@ class API { }); // When we are processing JSON, allow to keep the new env by default - env.updateEnv = true; + env.updateEnv = typeof(opts.updateEnv) === 'undefined' ? true : opts.updateEnv; // Pass `env` option that._operate(action, proc_name, env, function(err, ret) { diff --git a/lib/Utility.js b/lib/Utility.js index 547ec9bf6c..fd35269f81 100644 --- a/lib/Utility.js +++ b/lib/Utility.js @@ -33,10 +33,10 @@ var Utility = module.exports = { }, extendExtraConfig : function(proc, opts) { if (opts.env && opts.env.current_conf) { - if (opts.env.current_conf.env && - typeof(opts.env.current_conf.env) === 'object' && - Object.keys(opts.env.current_conf.env).length === 0) - delete opts.env.current_conf.env + // NOTE: `env` gets overriden by `Utility.extendMix` call. Instead, we want to merge envs. + if (opts.env.current_conf.env && typeof(opts.env.current_conf.env) === 'object') + Utility.extendMix(proc.pm2_env.env, opts.env.current_conf.env); + delete opts.env.current_conf.env; Utility.extendMix(proc.pm2_env, opts.env.current_conf); delete opts.env.current_conf;