In the world of Node.js applications, ensuring that your applications are robust and resilient to unexpected downtime is crucial. PM2 (Process Manager 2) is a powerful tool used to manage production workloads with ease. One of the essential features it offers is the ability to keep processes running across server reboots seamlessly. This is primarily achieved through the use of two fundamental commands: pm2 save
and pm2 startup
. In this blog post, we’ll dive deep into how these commands work and why they are critical for maintaining application uptime.
Before we delve into specifics, let's quickly revisit what PM2 is. PM2 is a popular process manager for Node.js applications. It allows you to define, manage, and monitor your applications easily. With features like clustering, log management, monitoring, and load balancing, PM2 helps ensure that your applications run smoothly in a production environment.
pm2 save
The command:
pm2 save
The primary purpose of the pm2 save
command is to create a snapshot of your current running PM2 processes. This snapshot is written to a file located in the PM2 directory (~/.pm2/dump.pm2). Think of it as a backup of your current process list, which includes all the details necessary to restart these processes later.
pm2 save
after starting or stopping any application changes you wish to persist across reboots. It’s a good practice to make this a habit whenever you modify your process list.pm2 startup
The command:
pm2 startup
The pm2 startup
command generates and configures a startup script specific to your system's init system (e.g., systemd, upstart, launchd). This script ensures that the PM2 daemon starts on boot, enabling any saved processes to be resurrected automatically.
pm2 startup
takes care of configuring your system to launch PM2 automatically during boot.pm2 save
? While pm2 startup
ensures the PM2 daemon runs on boot, it’s pm2 save
that ensures your specific processes are restored. Without both, your applications may not return to their previous state after a reboot.Here's a simple step-by-step guide to making sure your Node.js applications are managed across reboots:
pm2 start app.js
pm2 save
After executing this command, follow any additional instructions provided by PM2 to run the generated command with root privileges.
pm2 startup
pm2 ls
One time, I had a Nuxt app running on my VPS. After that, I upgraded the VPS, and of course, it needed to reboot. This time, my app does not start up successfully with pm2 because my VPS uses the old version of Node is 12, but my application works well with Node 20. So I switched to Node 20, but PM2 still keeps the old version is 12, so when I run pm2 start, I got an error like this:
0|LazyCode | Listening on http://[::]:3000
/root/.pm2/logs/LazyCodet-Nuxt-out-2.log last 15 lines:
/root/.pm2/logs/LazyCodet-Nuxt-out-3.log last 15 lines:
/root/.pm2/logs/LazyCodet-Nuxt-error-0.log last 15 lines:
0|LazyCode | at WriteStream.<anonymous> (/usr/local/lib/node_modules/pm2/lib/Utility.js:186:13)
0|LazyCode | at WriteStream.emit (events.js:314:20)
0|LazyCode | at internal/fs/streams.js:366:10
0|LazyCode | at FSReqCallback.oncomplete (fs.js:156:23)
0|LazyCode | Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /var/www/nuxt-app/releases/release-215/server/index.mjs
0|LazyCode | at Module.load (internal/modules/cjs/loader.js:861:11)
0|LazyCode | at Function.Module._load (internal/modules/cjs/loader.js:708:14)
0|LazyCode | at /usr/local/lib/node_modules/pm2/lib/ProcessContainer.js:304:25
0|LazyCode | at wrapper (/usr/local/lib/node_modules/pm2/node_modules/async/internal/once.js:12:16)
0|LazyCode | at next (/usr/local/lib/node_modules/pm2/node_modules/async/waterfall.js:96:20)
0|LazyCode | at /usr/local/lib/node_modules/pm2/node_modules/async/internal/onlyOnce.js:12:16
0|LazyCode | at WriteStream.<anonymous> (/usr/local/lib/node_modules/pm2/lib/Utility.js:186:13)
0|LazyCode | at WriteStream.emit (events.js:314:20)
0|LazyCode | at internal/fs/streams.js:366:10
0|LazyCode | at FSReqCallback.oncomplete (fs.js:156:23)
...
I'm so crazy about this error. When I got this error, I searched the issue with the key "Error [ERRREQUIREESM]: Must use import to load ES Module" but you know, this is the wrong direction.
So I spent 6 hours on this, and I realized the issue. I found a solution [1] to update PM2 using the current node version:
pm2 update
And I found a useful command to check the information of PM2, and of course, it consist of the version is used by PM2
pm2 monit
This is the UI of it:
Understanding and utilizing pm2 save
and pm2 startup
is vital for any developer or system administrator aiming to maintain high availability for Node.js applications. By saving your process list and ensuring that PM2 itself starts on boot, you gain peace of mind knowing your applications will automatically resume after a system reboot. Implement these practices to enhance your application's resilience and reliability with PM2.