Just experimenting with dtruss/dtrace here. I have this command:
sudo dtruss node server.js &> my-dtruss.log
that log looks like this: https://gist.github.com/ORESoftware/9b4d47682a8f0ec25330c02b4ef3ea2d
my question is, if my NODE_ENV var is set, why is it unset for child processes of dtruss command? and how can I set env variables for the node process?
my node server crashes if NODE_ENV is not set, so that's why I assume the dtruss output ends and does not continue.
Related
Recently I made a simple API server using node.js+express. And the script below is a part of my package.json file I use to run with npm commands.
"scripts": {
...
"release": "cross-env NODE_ENV=production MODE=release node server/app.js",
}
After I starts the server with npm run release, I can see multiple processes such as below are running on my Linux server.
/bin/sh /api/node_modules/.bin/cross-env NODE_ENV=development MODE=test node server/app.js
node /api/node_modules/.bin/../cross-env/bin/cross-env.js NODE_ENV=development MODE=test node server/app.js
node server/app.js
I read a related documentation here, but I don't understand what actually happens in background.
What is the order of creating processes? npm => /bin/sh => node /api/.. => node server/app.js ?
What does each process do? All three processes are necessary to run my server?
If I wants to kill the server with pid, which process id should I use?
What is the order of creating processes? npm => /bin/sh => node /api/.. => node server/app.js ?
What does each process do? All three processes are necessary to run my server?
Well, the flow is like this:
NPM is spawned (you run it) inside your shell, npm itself runs with NPX in order to set the local path.
Your npm script spawns a process from a package called cross-env for cross-OS environment variable setting.
That process in turn spawns Node.js (after setting the environment variables)
That's why you see 3 processes. After your server itself run - only the actual server process is needed to run the server.
If I wants to kill the server with pid, which process id should I use?
This one: node server/app.js - since that's your actual server, the others are just "utility processes" (one for the npm script you ran and the other for the environment variables").
It's worth mentioning that in general - servers are run inside containers or other orchestrators/managers that have built-in logic for restarting/killing the process. Typically the orchestrator sends SIGTERM to the process.
Platform: Windows
What I want to do is simple: start pm2 (without any .json scripts) and have my node web app (ExpressJS) access the env. variable.
when I do set
> set MODE=test
and then do
> npm start
I can access process.env.MODE which gives me 'test' exactly as I wanted.
Now I can't seem to figure out how to do this in pm2. If I
> set MODE=test
and then do
pm2 start ./bin/www
I get process.env.MODE is undefined
I also tried
pm2 start ./bin/www -x -- --MODE=test
also tried
set MODE="test" & pm2 start ./bin/www
and
set MODE=test & pm2 start ./bin/www
Nothing seems to work. What am I doing wrong? What should I do instead?
On Windows SET sets an environment variable in the current CMD session. You may need to SET your environment variable in the same CMD session that you are running pm2 from.
Alternately, use SETX to set a permanent environment variable. You need to close and re-open and CMD sessions in order to make an environment variable set with SETX available in all CMD sessions.
refer: https://superuser.com/questions/916649/what-is-the-difference-between-setx-and-set-in-environment-variables-in-windows
How can i define enviroment at NodeJS, Express4?
Don't work. Output error in console.
NODE_ENV=production node app.js
EDIT:
http://rghost.net/57634264/image.png
"NODE_ENV" is unknown command.
From the express 4 documentation:
settings
The following settings will alter how Express behaves:
env Environment mode, defaults to process.env.NODE_ENV (NODE_ENV environment variable) or "development"
Start your app with the command you posted:
NODE_ENV=production node app.js
If you've used express correctly (can't tell here as you've not posted code), you can access NODE_ENV through the app.get() method, which, in this context, will get the setting variable.
if (app.get('env') == 'production') {
// do something only production does
}
This is because windows CMD is a lot different than POSIX-like shells (used in linux and osx), which is what most of the tutorials and documentation for node userland is written for.
I recommend either using the Git Bash terminal that comes with git(link) to get a POSIX-like shell, or use the windows command to set the variable (takes two commands):
set NODE_ENV=production
node app.js
The command I run on my server to start my node app is:
sudo IS_PROD=1 node app.js
I have forever installed but can't seem to pass in the environment variable.
sudo IS_PROD=1 forever node app.js
Doesn't seem to do the trick. I have tried several varieties of this. How do I either execute this command successfully or permanently set the environment variable?
First of all you should skip the node thing in you command, it should not be there, you should not be able to execute that. forever automatically starts your script using nodejs. Instead you should do like this;
sudo IS_PROD=1 forever app.js
Probably you, instead of starting your server in foreground, will want to start your server as a daemon. eg.
sudo IS_PROD=1 forever start app.js
This will create a process in the background that will watch your node app and restart it when it exits. For more information see the readme.
Both of these methods preserves the environment variables, just like when you are just using node.
app.js:
console.log(process.env.IS_PROD);
Using node (v0.8.21)
$ node app.js
undefined
$ IS_PROD=1 node app.js
1
$ sudo IS_PROD=1 node app.js
1
Using forever (v0.10.0)
$ forever app.js
undefined
$ IS_PROD=1 forever app.js
1
$ sudo IS_PROD=1 forever app.js
1
Documentation:
process.env
An object containing the user environment. See environ(7).
A web app I am writing in JavaScript using node.js. I use Foreman, but I don't want to manually restart the server every time I change my code. Can I tell Foreman to reload the entire web app before handling an HTTP request (i.e. restart the node process)?
Here's an adjusted version of Pendlepants solution. Foreman looks for an .env file to read environment variables. Rather than adding a wrapper, you can just have Foreman switch what command it uses to start things up:
In .env:
WEB=node app.js
In dev.env:
WEB=supervisor app.js
In your Procfile:
web: $WEB
By default, Foreman will read from .env (in Production), but in DEV just run this:
foreman start -e dev.env
You can use rerun for this purpose
You might implement just 2 commands for this:
gem install rerun
rerun foreman start
Then rerun will automatically restart process after any change in your files.
If you use nodemon
, you can do
nodemon --exec "foreman start"
The problem isn't with Foreman so much as it's with how node doesn't reload code on new requests. The solution is to use an npm package like supervisor along with an environment wrapper for Foreman.
First, install supervisor:
npm install -g supervisor
Then, write a wrapper shell script that Foreman can call:
if [ "$NODE_ENV" == "production" ]; then
node /path/to/app.js
else
supervisor /path/to/app.js
fi
Set the wrapper script's permissions to executable by running chmod a+x /path/to/wrapper_script.sh
Lastly, update foreman to use the wrapper script. So in your Procfile:
web: /path/to/wrapper_script.sh
Now when you run Foreman and your node app isn't running in production, it should reload on every request.
I feel like Peter Ehrlich's comment on the original question deserves to be an answer on its own. I think a different Procfile for local/dev is definitely the best solution: https://stackoverflow.com/a/10790514/133720
You don't even need to install anything new if you use node-dev.
Your .env file loaded from Procfile:
NODECMD=node-dev
Your Procfile:
web: $NODECMD app/server.js
Your foreman command
foreman start -e dev.env -p 9786
And in your production env (heroku) set an environment variable:
NODECMD=node