Introduction
For many people, actually running your code in a production environment is an afterthought, and just writing the code is where the real challenge is. While this is mostly true in my experiences, finding a reliable and easy way to run your app can be pretty difficult itself.
There are a few things you need to consider when running your app(s).
- Where will the output/logs go?
- What happens if the app crashes?
- How do I keep track of all my daemon processes?
- How do I provide configurations for each process?
This is where the Node forever
package is really useful. It helps you easily manage all of the above problems and more, which I'll describe in the next few sections.
What is Forever?
forever
is a command-line utility for Node applications written entirely in JavaScript. It is meant to simplify your life in a production environment by managing (starting, stopping, restarting, etc) Node processes and their configurations. You can use it on the command line or programmatically (via forever-monitor
) within your Node code.
You can specify these configurations via the command line or a JSON configuration file. I personally prefer the JSON file since you can configure multiple Node processes in a single file, making it easy to launch all of your processes at once. This way I don't hesitate to break up a big monolith into multiple independent services since managing them will be much easier thanks to utilities like forever
.
It works underneath by running Flatiron server as a daemon process to manage your other daemon processes, so if/when your code fails and crashes, forever
will be there to automatically restart it and hopefully avoid downtime for your users. Running forever
with a Flatiron server is an easy way to keep the utility up and running while monitoring for user input, and thanks to the CLI plugin this was easy for the forever
developers to do. If you're going to create a program like forever
(i.e., a long-running daemon process that receives user commands) then I'd highly recommend you do it this way. It will make things a whole lot easier.
The interprocess communication happens via sockets, which is handled by the high-level nssocket
library. The socket files that allow communication to be re-opened between processes reside in [forever.root]/socks
. Naturally, the messages between the processes are serialized as JSON. It's another helpful library to check out if you ever want event-based socket communication.
I should note, one important feature about forever
(and other process management tools like it) is that you can use it for non-Node applications as well, like Python, Ruby, etc. The -c
, or command flag (which you'll see later), lets you tell forever
how to run your app. Using this, you can tell it to use any other interpreter for execution, like Python:
$ forever start -c python py_script.py
So even if you don't like Node, or just need to use a different language for a project, keep in mind that this is still useful to you.
How to use Forever
Ok, on to the important part, how to actually use the damn thing. Let's start out with a simple example, like just starting and stopping a web-app. For our example, we'll be starting and stopping a "hello world" Express server:
// index.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(8080);
Install forever
with npm install forever -g
, and start the server with:
$ forever start -a index.js
This will launch the Express app as a background process. The -a
flag appends logs to the default log file located in forever
's root directory (~/.forever
by default on Unix systems). You won't be able to start
the app without this flag if the log file already exists.
Inspect the running process with forever list
:
info: Forever processes running
data: uid command script forever pid id logfile uptime
data: [0] moMB /Users/scott/.nvm/versions/node/v4.1.2/bin/node index.js 21389 21390 /Users/scott/.forever/moMB.log 0:0:0:3.345
To stop the process, just refer to it by id (21390
), UID (moMB
), PID (21389
), index (0
), or script name (index.js
):
$ forever stop index.js
While this is nice, it could be better. index.js
isn't very unique to our app, and the PID is hard to remember, so why give it a better name? That way you don't have to keep running forever list
to get info on your running process.
$ forever start -a --uid myapp index.js
Now you can just stop it with:
$ forever stop myapp
Two arguments on the command line isn't so bad, but it can become a bit much when you start adding arguments for log files, different Node executables, working directories, and more. So instead of specifying everything on the command line, you can use a JSON configuration file like this:
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
{
// Comments are allowed!
"uid": "myapp",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/home/scott/myapp",
"command": /Users/scott/.nvm/versions/node/v4.1.2/bin/node
}
Assuming this file is in your current working directory and named forever.json
, use it like this:
$ forever start ./forever.json
As you can see, you can even tell forever
which version of Node to use, which is really convenient when you have multiple apps on a single server that require different versions (like the io.js
fork).
[
{
// App using Node v0.11.8
"uid": "myapp1",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/Users/scott/myapp1",
"command": "/Users/scott/.nvm/versions/node/v0.11.8/bin/node"
},
{
// App using io.js
"uid": "myapp2",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/Users/scott/myapp2",
"command": "/Users/scott/.nvm/versions/io.js/v2.2.1/bin/node",
"args": ["--port", "8080"]
}
]
Conclusion
There are a few tools to help you run Node apps, most notably forever
and pm2
. I've tried both and thought forever
was a bit easier to use (mostly just because it's simpler and has less features/options to worry about), while pm2
is more powerful. If you're really feeling ambitious, you can try out pm2
's cluster mode or API to help monitor metrics about your running app.
What other interesting configurations and uses do you have for process management tools like forever
? Let us know in the comments!