Keeping Node.js Server Run Permanently Using Process Managers

Keeping Node.js Server Run Permanently Using Process Managers

 

Introduction

Node.js is an open-source, cross-platform, back-end JavaScript runtime environment that has a double-edged sword feature of allowing developers to build a complete application for both the front and the back end with just one programming language.

Once the Node.js application has been deployed to a server to host the application, the application needs to be running always. The challenging part of maintaining an application is keeping it running continuously. There are instances where the application would stop running for encountering an unexpected crash, an exception, a bug, or an IO failure. Like a good runtime, Node will stop running if it won’t be able to handle these kinds of issues. This is a good expected behavior of Node but you will have to manually restart it once the application is down.

In this article, we will highlight Forever, PM2, and StrongLoop, the popular open-source process managers that you can use to be able to automatically run a node application continuously in production.

There are OS-level services like systemd service on Linux, or a Windows Service on Windows that can restart a crashed Node app. These are simpler to use since we’ll just run our app directly in the init system but we won’t be able to get the features and additional privileges of using a process manager.

About Process Manager

Node.js process manager is a useful tool for deploying a project in the production environment since it ensures that a Node.js process or script runs continuously. It simplifies how you can manage the application at runtimefacilitating common system administration tasks such as restarting when a failure is encountered, stopping it, modifying environment variables/settings, checking performance metrics, and others. It also supports application logging, load balancing, clustering, docker support, multi-host deployment, graphical console, and other useful process management features.

Using Forever

Forever is a simple command-line interface tool written entirely in JavaScript to ensure that a script runs continuously. It aims to simplify managing node processes in a production environment like starting, stopping, restarting, etc. Forever’s straight-forward interface makes it ideal for running smaller deployments of Node.js apps. When the server is stopped because of some error or exception, it automatically restarts it. It also supports several usage options which you can pass directly from the command line or pass them in a JSON file.

There are two ways to use forever: through the command line interface, or by embedding the forever module in the code.

Installation

A. Through the command line interface

1. To install forever, use this command:

[sudo] npm install -g forever

2. Then start your application using:

forever app.js

Or as a service:

forever start app.js

Replace app.js with the name of the file that is your app’s main entry point.

You will see an output like this:

$ forever start app.js
warn: --minUptime not set. Defaulting to: 1000ms
warn: --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info: Forever processing file: app.js

It’s safe to ignore the warnings but if you want to explicitly set them, you can refer to the forever –help command. Here’s a sample command to set up the minUptime and spinSleepTime:

forever start --minUptime 1000 --spinSleepTime 1000 app.js

3. To check all processes listed up which are registered with forever, enter this command:

forever list

You will see an output like this:

$ forever list
info: Forever processes running
data: uid command
script forever pid id logfile uptime
data: [0] BQL5 /home/dh_df4zyr/.nvm/versions/node/v12.18.3/bin/node app.js 10 818 14388 /home/dh_df4zyr/.forever/BQL5.log 0:0:0:1.642

4. To make sure that the application will automatically restart itself when the server reboots, we will need to create an auto-start script using crontab. It is a file which contains the schedule of cron entries to be run and at specified times.

Use this command to edit your crontab file:

crontab -e

Then add this line to the bottom of the file and save it:

@reboot forever start /home/node/app/app.js

Just replace app.js with the name of your file. By adding this, crontab will run the forever start command after the system reboots.

B. Using it programmatically

You can use forever inside your own Node.js code using forever-monitor.

1. Embed this code to your app.js file and save it:

var forever = require('forever-monitor'); 
var child = new(forever.Monitor)('app.js', {
max: 3, silent: true, options: [] });
child.on('exit', function() {
console.log('app.js has exited after 3 restarts'); });
child.start();

2. Install forever-monitor

$ npm install forever-monitor

Here are some options available when using Forever programmatically which most of this configuration is just optional.

  {

    //

    // Basic configuration options

    //

    'silent': false,            // Silences the output from stdout and stderr in the parent process

    'uid': 'your-UID',          // Custom uid for this forever process. (default: autogen)

    'pidFile': 'path/to/a.pid', // Path to put pid information for the process(es) started

    'max': 10,                  // Sets the maximum number of times a given script should run

    'killTree': true,           // Kills the entire child process tree on `exit`

 

    //

    // These options control how quickly forever restarts a child process

    // as well as when to kill a "spinning" process

    //

    'minUptime': 2000,     // Minimum time a child process has to be up. Forever will 'exit' otherwise.

    'spinSleepTime': 1000, // Interval between restarts if a child is spinning (i.e. alive < minUptime).

 

    //

    // Command to spawn as well as options and other vars

    // (env, cwd, etc) to pass along

    //

    'command': 'perl',         // Binary to run (default: 'node')

    'args':    ['foo','bar'],  // Additional arguments to pass to the script,

    'sourceDir': 'script/path',// Directory that the source script is in

 

    //

    // Options for restarting on watched files.

    //

    'watch': true,               // Value indicating if we should watch files.

    'watchIgnoreDotFiles': null, // Whether to ignore file starting with a '.'

    'watchIgnorePatterns': null, // Ignore patterns to use when watching files.

    'watchDirectory': null,      // Top-level directory to watch from. You can provide multiple watchDirectory options to watch multiple directories (e.g. for cli: forever start -w='app' -w='some_other_directory' app\index.js)

    //

    // All or nothing options passed along to `child_process.spawn`.

    //

    'spawnWith': {

      customFds: [-1, -1, -1], // that forever spawns.

      setsid: false,

      uid: 0,      // Custom UID

      gid: 0,      // Custom GID

      shell: false // Windows only - makes forever spawn in a shell

    },

    //

    // More specific options to pass along to `child_process.spawn` which

    // will override anything passed to the `spawnWith` option

    //

    'env': { 'ADDITIONAL': 'CHILD ENV VARS' },

    'cwd': '/path/to/child/working/directory',

 

    //

    // Log files and associated logging options for this instance

    //

    'logFile': 'path/to/file', // Path to log output from forever process (when daemonized)

    'outFile': 'path/to/file', // Path to log output from child stdout

    'errFile': 'path/to/file', // Path to log output from child stderr

 

    //

    // ### function parseCommand (command, args)

    // #### @command {String} Command string to parse

    // #### @args    {Array}  Additional default arguments

    //

    // Returns the `command` and the `args` parsed from

    // any command. Use this to modify the default parsing

    // done by 'forever-monitor' around spaces.

    //

    'parser': function (command, args) {

      return {

        command: command,

        args:    args

      };

    }

 }

Managing Processes

Here are some useful forever commands to manage your node application. You can view these using this command:

$ forever --help

Using PM2

PM2 is a production process manager for Node.js applications that enables you to keep applications alive forever. It has a built-in load balancer, reloads applications without downtime, helps in managing application logging, CPU/memory monitoring, and clustering, Docker and Heroku integration, behavior configuration, module management, hot reload, startup script generator, and revision tracing.

Installation

A. Through the command line interface

1. Install PM2 by running the command:

npm install pm2 -g

2. Start the application that you want to keep running forever:

pm2 start app.js

You will have an output like this:

Here are some options you can pass to the CLI:

# Specify an app name
--name

# Watch and Restart app when files change
--watch

# Set memory threshold for app reload
--max-memory-restart <200MB>

# Specify log file
--log

# Pass extra arguments to the script
-- arg1 arg2 arg3

# Delay between automatic restarts
--restart-delay

# Prefix logs with time
--time

# Do not auto restart app
--no-autorestart

# Specify cron for forced restart
--cron

# Attach to application log
--no-daemon

B. Using it programmatically

PM2 can be used by embedding it directly in your code, spawn processes, keep them alive even if the main script is exited. This option is useful when deploying a Node.js application in any kind of cloud provider.

Embed this code to your node file:

var pm2 = require('pm2');

pm2.connect(function(err) {
if (err) {
console.error(err);
process.exit(2);
}

pm2.list((err, list) => {
console.log(err, list)
})

pm2.stop(‘app-name’, (err, proc) => {
})

pm2.restart(‘app-name’, (err, proc) => {
})

pm2.start({
script : ‘app.js’, // Script to be run
exec_mode : ‘cluster’, // Allows your app to be clustered
instances : 4, // Optional: Scales your app by 4
max_memory_restart : ‘100M’ // Optional: Restarts your app if it reaches 100Mo
}, function(err, apps) {
pm2.disconnect(); // Disconnects from PM2
if (err) throw err
});
});

2. Instruct PM2 to start our application by executing its index.js script.

pm2 start app.js

You will have an output like this:

Managing Processes

There are many options available to manage your application with PM2 which will be helpful depending on your use case. Here are some useful commands for monitoring PM2 processes:

# Fork mode

pm2 start app.js --name my-api # Name process

# Cluster mode

pm2 start app.js -i 0        # Will start maximum processes with LB depending on available CPUs
pm2 start app.js -i max      # Same as above, but deprecated.
pm2 scale app +3             # Scales `app` up by 3 workers
pm2 scale app 2              # Scales `app` up or down to 2 workers total

# Listing

pm2 list               # Display all processes status
pm2 jlist              # Print process list in raw JSON
pm2 prettylist         # Print process list in beautified JSON

pm2 describe 0         # Display all informations about a specific process

pm2 monit              # Monitor all processes

# Logs

pm2 logs [–raw]       # Display all processes logs in streaming
pm2 flush              # Empty all log files
pm2 reloadLogs         # Reload all logs

# Actions

pm2 stop all           # Stop all processes
pm2 restart all        # Restart all processes

pm2 reload all         # Will 0s downtime reload (for NETWORKED apps)

pm2 stop 0             # Stop specific process id
pm2 restart 0          # Restart specific process id

pm2 delete 0           # Will remove process from pm2 list
pm2 delete all         # Will remove all processes from pm2 list

# Misc

pm2 reset     # Reset metadata (restarted time…)
pm2 updatePM2          # Update in memory pm2
pm2 ping               # Ensure pm2 daemon has been launched
pm2 sendSignal SIGUSR2 my-app # Send system signal to script
pm2 start app.js –no-daemon
pm2 start app.js –no-vizion
pm2 start app.js –no-autorestart

When you start an app using pm2, the app is immediately sent to the background. You can control the background app from the command line by these commands.

Monitoring using PM2 web-based dashboard

You can easily manage your Node.js application with PM2 using PM2.io, a web-based monitoring dashboard. It features issues and exception tracking, deployment reporting, real-time logs, email and slack notification, custom metrics monitoring, and custom actions center. It has a free plan that allows you to connect up to 4 servers/applications.

Using StrongLoop

StrongLoop is a production process manager for Node.js applications with built-in load balancing, monitoring, keep processes and clusters alive forever, docker support, multi-host deployment, and a graphical console. Note that StrongLoop runs on port 8701 by default, so check your port if it’s blocked by the host system.

1. Install the full StrongLoop module that includes the client tools (Arc and slc) and StrongLoop Process Manager using this command:

[sudo] npm install -g strongloop

2. Start the application by:

slc start

3. View the app status with all worker PIDs, cluster IDs, and other key information.

slc ctl

You will see an output like this:

$ slc ctl
Service ID: 1
Service Name: node-app
Environment variables:
No environment variables defined
Instances:
Version Agent version Cluster size
4.1.13 1.5.14 4
Processes:
ID PID WID Listening Ports Tracking objects? CPU profiling?
1.1.56241 56241 0
1.1.56242 56242 1 0.0.0.0:3001
1.1.56243 56243 2 0.0.0.0:3001
1.1.56244 56244 3 0.0.0.0:3001
1.1.56245 56245 4 0.0.0.0:3001

Managing Processes

slc ctl stop                # stop the application
slc ctl restart             # restart the application
slc ctl soft-restart        # soft reboot application
slc ctl cpu-start           # start the CPU profiler for the process
slc ctl cpu-stop            # stop the CPU profiler
slc arc                     # Start StrongLoop Arc
slc ctl log-dump example-app --follow         # to follow logs live in the console
slc ctl cpu-start           # start the CPU profiler for the process
slc ctl stop                # stop the application
slc ctl restart             # restart the application
slc ctl soft-restart        # soft reboot application
slc ctl cpu-start           # start the CPU profiler for the process
slc ctl cpu-stop            # stop the CPU profiler
slc arc                     # Start StrongLoop Arc
slc ctl log-dump example-app --follow         # to follow logs live in the console
slc ctl cpu-start           # start the CPU profiler for the process
slc ctl cpu-stop            # stop the CPU profiler for the process
slc ctl heap-snapshot       # generate heap snapshots ctl cpu-stop            # stop the CPU profiler for the process

slc ctl heap-snapshot       # generate heap snapshots

Conclusion

Using Node.js process managers allows us to focus on building seamless applications without worrying about the massive overhead that is required to keep an application up and running. 

Each has its strengths and weaknesses: forever is the most general and its simple interface makes it ideal for running smaller application deployments, both PM2 and StrongLoop have a wide range of features that are best suited for production concerns. But the edge of StrongLoop among these process managers is it provides a comprehensive runtime and deployment solution that address the entire Node application life cycle. It has a load balancer auto-configuration, heap and CPU profiles, and triggers profiling based on slow event loop.

Using any of these three tools can be very helpful but it’s up to you to decide how a given tool will fit into a workflow and whether or not a solution matches the scope of your needs or issues you’ve encountered.

Leave a Reply

Your email address will not be published. Required fields are marked *