To totally unlock this section you need to Log-in
Let's take a look to the following scenario: we have a node.js server/app and we start it by using npm start & (background mode) command through Putty. But the problem is that if we close Putty (or any other SSH client) the server will be stopped after sometime.
So, our main need, in this scenario, is to instruct the system to keep the nodejs app (app.js), so our application, alive while not connected through SSH on the system itself, in interactive mode. This leads to the need to "transform" the specific app.js (starting it with npm start) command into a daemon, basically into a system service.
To address this scenario there are two possible, reliable, approaches: pm2 and forever.
PM2
PM2 is a daemon process manager that will help you manage and keep your application online 24/7 (https://github.com/Unitech/pm2).
Some advantages of running your application using PM2 are the following:
- PM2 will automatically restart your application if it crashes.
- PM2 will keep a log of your unhandled exceptions - for example, in a file at /home/example_user/.pm2/logs/app-err.log.
- With one command, PM2 can ensure that any applications it manages restart when the server reboots. Basically, your node application will start as a service.
We can install it by simply running the following command in npm:
sudo npm install pm2 -g
To update PM2 the process is simple:
npm install pm2 -g && pm2 update
Then we can update the in-memory PM2 daemon via command:
pm2 update
After the PM2 update is also recommended to update also the PM2 startup script (if used) running:
$ pm2 unstartup $ pm2 startup
To check the version of PM2 installed on the system, execute the below command:
pm2 --version
Then we can, moving into the working directory of our application on the system (for example in /var/www/html, if we have placed it there), instruct pm2 to keep alive our app by running a similar command (the --name option is not mandatory, but recommended to identify out app later using pm2 command line utility):
pm2 --name HelloWorld start npm -- start
We can list running processes in pm2:
pm2 ps
Each process will have a unique id , using which we can manage a particular process , Instead of restarting the entire app.
Stop it if needed by using the following command, specifying the id of the app that we need to stop:
pm2 delete 0
NOTE: we can use process name instead of ID (if provided).
We can also check the pm2 logs to see if there are issues or problems with apps running with pm2:
pm2 logs
To check the logs for a particular process or for a specific application:
pm2 logs 4 pm2 logs sample-app
To know more details about a particular process, then run this command:
pm2 show 0
To stop a process or an application we can use the below command:
pm2 stop 8 pm2 stop sample-app
To flush all the logs for all the applications, execute the below command:
pm2 flush
To enable the PM2 to automatically start on system bootup (so pm2 will be daemonized (with pm2-root name) and also all the apps that are running in it will be automatically saved for future reboots), the following command will create a automatically-configured startup script for the system:
pm2 startup
To save the lists of processes so that the processes will be automatically started after the system reboot:
pm2 save
To manually restore the previously saved processes:
pm2 resurrect
If you wish to disable PM2 from starting automatically on system boot, Execute the below command:
pm2 unstartup
Another useful aspect is that PM2 offers a declaration file to comprehensively define every app which should be started when using this file (in JSON format).
The following JSON declaration file is an example on how to define two different NodeJS apps, called apps.json:
{ "apps": [ { "name": "futurestudio-homepage", "script": "./homepage/server.js", "instances": 2, "exec_mode": "cluster", "env": { "NODE_ENV": "production", "PORT": "3000", } }, { "name": "blog", "script": "./blog/index.js", "instances": 1, "exec_mode": "fork", "env": { "NODE_ENV": "production", "PORT": "4000", } } ] }
Within the root object, we are defining an apps array containing all apps which get started by PM2 using this declaration file. Each application declaration is wrapped into its own JSON object. Additionally, each object within the apps array defines multiple app properties. These properties represent the options you would use on PM2’s command line utility.
The exemplary declaration file above defines two apps: homepage and blog. We can now start both applications by running this .json file with PM2:
pm2 start apps.json
Of course we can use other PM2 commands referencing this JSON file:
# Start processes pm2 start apps.json # Restart processes pm2 restart apps.json # (Graceful) Reload processes pm2 reload apps.json # Stop processes pm2 stop apps.json # Delete processes pm2 delete apps.json
Remember: If we are executing the PM2 commands on the app declaration file, our command will affect each defined application. We can restart, stop, or delete a single application using the command line utility, as usual.
The following list depicts available options within our JSON app declaration file:
- name: application name, e.g. "blog"
- cwd: app location from where it will be launched, e.g. "/blog"
- args: additional arguments passed to your app, e.g. ["testing"]
- script: the script which will be executed to start an app, e.g. "/blog/app.js,
- node_args: additional Node.js arguments when launching your app, e.g. ["--harmony", " --max-stack-size=102400000"]
- timestamp: format of dates in your log files, e.g. "YYYY-MM-DD HH:mm Z"
- error_file: location of your apps error log file, e.g. "logs/blog.stderr.log"
- out_file: location of your apps out log file, e.g. "logs/blog.stdout.log"
- pid_file: location of your apps .pid file, e.g. "pids/blog.pid"
- instances: number of worker processes for your app. Allowed values: positive integer including 0 or 'max'
- min_uptime: minimum uptime before PM2 starts to restart an app in case of errors, e.g. "20s" (20 seconds), default value is 1s
- max_restarts: maximum restart count before PM2 gives up to get your app online, e.g. 10, default value is 15
- max_memory_restart: maximum memory amount before PM2 restarts your app, e.g. "100M" (100 megabytes), allowed values: "1G", "50M", "4K"
- cron_restart: cronjob pattern to restart your app, e.g. `"0 1 * * *",
- watch: watch the app folder for file changes in restart the app if a change is detected, default value is false, allowed values are true|false
- ignore_watch: regex list of files or folders to be ignored when watching an app, e.g. ["[\\/\\\\]\\./", "node_modules"]
- merge_logs: defines whether the logs of all app worker instances will be merged into the same file, default value is false, allowed values true|false
- exec_interpreter: interpreter of your app, e.g. "node"
- exec_mode: execution mode of your app (can also be defined by the instances field), e.g. "fork", allowed values fork|cluster
- autorestart: if enabled, PM2 will automatically restart apps on crashes, e.g. false, default is true, allowed values true|false
- vizion: integrates version control metadata with PM2, default value is true, allowed values are true|false
- env: environment varibles for your app, specified as a nested object, like env: { "NODE_ENV": "production", "AWESOME_SERVICE_API_TOKEN": "xxx" }
Every command line option is also available within the declaration file.
It is useful to note that we can create a sample ecosystem.config.js configuration file, using the following command:
$ pm2 init simple
This will generate a sample ecosystem.config.js that we can extend to define our NodeJS apps, but not only, and specific properties:
module.exports = { apps : [{ name : "app1", script : "./app.js" }] }
Once defined multiple apps into this configuration file (that needs to end with the .config.js text to be valid in pm2), we can manage all of them by controlling directly the ecosystem.config.js with the following commands:
# Start all applications pm2 start ecosystem.config.js # Stop all pm2 stop ecosystem.config.js # Restart all pm2 restart ecosystem.config.js # Reload all pm2 reload ecosystem.config.js # Delete all pm2 delete ecosystem.config.js
Finally, we need to consider also that we can define "environments" for each app defined into a JSON (or YAML) configuration file (or into ecosystem.config.js).
Depending on the application setup and execution context we want to make use of different values within your process specific environment variables. Environment variables are a convenient and commonly used way to inject context specific options to the app and pass specific parameters/values to it.
The following example process file defines four different environments, each having their own key-value-pairs: env, env_develop, env_production, env_test. Environments in a PM2 process file follow the schema of env_* where * is the placeholder for your desired environment name.
The following example uses JSON format for the process file. We call the following process file app.json.
{ "apps": [ { "name" : "futurestudio-homepage", "script" : "./server.js", "exec_mode" : "cluster", "instances" : 2, "env": { "DB_USER" : "root", "DB_PASS" : "root" }, "env_develop": { "NODE_ENV" : "develop" }, "env_production" : { "NODE_ENV" : "production", "PORT" : 2000, "DB_USER" : "username", "DB_PASS" : "secret-password" }, "env_test" : { "NODE_ENV" : "testing", "PORT" : 8000 } } ] }
Besides the attributes for name, script, exec_mode and instances, we can spot the individual environment configurations.
It is important to know that values within env are set as the default environment. We can override the default values if necessary in other environments.
Different environments within a PM2 process file are defined using the env_* keyword and replacing the star * with the appropriate name, like env_production. We can define as many different environments as you want by using differing names.
With multiple environments set up in your process file we can choose the one to start by adding the --env <environment> to the start command that references the process file.
Using the app.json file from above, we start the development environment like this:
$ pm2 start app.json --env develop
Within your application running in develop mode, the NODE_ENV variable is now accessible with the value develop (as defined), so the application will know that the variable NODE_ENV has develop value. If we will add more environment variables for env_develop within the process file, they will be exposed to our app as well.
Assuming that we want our app to just start in default mode (so using the env values), we can still reference the app.json file with the PM2 command line utility and only the values defined within env are passed and accessible by your application.
$ pm2 start app.json # will start your app using "env"
Starting your application with default values makes sense for development or testing purposes avoiding the extra typing to specify the environment.
Let's now consider that we want to switch to another environment: that’s straight forward: we need to use the --env <new-environment> argument with the new environment.
If we have already started our app in env_develop mode and we want to switch in env_production we can use the following approach:
$ pm2 restart app.json --env production
Besides pm2 restart, you can leverage every available command like reload to switch environments in zero-downtime manner.
Cluster Mode
An additional very importart feature usable in pm2 is the cluster mode.
The cluster mode allows networked Node.js applications (http(s)/tcp/udp server) to be scaled across all CPUs available, without any code modifications. This greatly increases the performance and reliability of your applications, depending on the number of CPUs available. Under the hood, this uses the Node.js cluster module such that the scaled application’s child processes can automatically share server ports.
To enable the cluster mode, just pass the -i option:
pm2 start app.js -i max
max means that pm2 will auto detect the number of available CPUs and run as many processes as possible:
Or using a js/yaml/json configuration file approach:
module.exports = { apps : [{ script : "api.js", instances : "max", exec_mode : "cluster" }] }
NOTE: you need to set the exec_mode to cluster so pm2 know you want to load balance between each instances, by default it will not.
Then to start the process file:
pm2 start processes.json
The -i or instances option can be:
- 0 or max to spread the app across all CPUs
- -1 to spread the app across all CPUs - 1
- number to spread the app across number CPUs
Using PM2 and its cluster mode there is also the possibility to scale the applications in real-time. If we need more or less workers than currently available, we can use PM2’s scale command and adjust the cluster size respectively:
pm2 scale <app-name> <number-of-workers>
The scale command is only available for processes that already run in cluster mode. PM2 won’t restart your app which currently runs in fork mode (so, the basic process spawning). You need to manually delete and restart it in cluster mode.
The following code block shows how to scale up the number of processes for the examplary sample app:
$ pm2 scale sample 6
Of course, PM2 allows you to scale down any app in real-time (in this case from 6 to 2 workers):
$ pm2 scale homepage 2
The previously running processes are deleted immediately and the number of workers reduced to your defined number.
We can also use a shortcut within PM2 which allows us to scale up or down your number of workers: pm2 scale sample +1 or pm2 scale sample -1: the first command will add another worker to sample and the second one removes a worker process.
Forever
Forever is, as PM2, a process manager for Node.js applications (but not only, as PM2); it keeps node.js applications running on production server and it utomatically restart server if it crashes or close, without any downtime. It is meant to simplify your life in a production environment by managing (starting, stopping, restarting, etc) Node processes and their configurations.
NOTE: one important feature about forever (and other process management tools like it) is that we can use it for non-Node applications as well, like Python, Ruby, etc. The -c, or command flag, let forever how to run your app: we can tell it to use any other interpreter for execution, like Python:
$ forever start -c python py_script.py
So even if we don't like Node, or just need to use a different language for a project, keep in mind that this could be still useful to know.
You can specify these configurations via command line or using a JSON configuration file. Using a JSON file we can configure/define multiple NodeJS processes in a single file, making it easy to launch all of your processes at once.
The general syntax of forever utility is shown below:
$ forever --help usage: forever [action] [options] SCRIPT [script-options] Monitors the script specified in the current process or as a daemon actions: start Start SCRIPT as a daemon stop Stop the daemon SCRIPT by Id|Uid|Pid|Index|Script stopall Stop all running forever scripts restart Restart the daemon SCRIPT restartall Restart all running forever scripts list List all running forever scripts config Lists all forever user configuration set <key> <val> Sets the specified forever configclear <key> Clears the specified forever config logs Lists log files for all forever processes logs <script|index> Tails the logs for Article NameRun node.js app as a daemon process (Linux)DescriptionWe have a node.js server/app and we start it by using npm start & (background mode) command through Putty. But the problem is that if we close Putty (or any other SSH client) the server will be stopped after sometime. We can use pm2 of forever process managers to address/fix this scenario.AuthorHeelpbookPublisher NameHeelpbook.net