功能
应用程序的转换状态 (重要)
PM2是进程管理器. PM2可以启动停止重启和删除进程.
启动进程:
$ pm2 start app.js --name "my-api"
$ pm2 start web.js --name "web-interface"
现在需要停止web-interface:
$ pm2 stop web-interface
你可以看到 the process hasn't disappeared. 仍然在那但是 stopped
状态.
重启它:
$ pm2 restart web-interface
现在我要从PM2进程列表 删除 这个应用:
$ pm2 delete web-interface
进程列表
列出所有运行进程:
$ pm2 list
# Or
$ pm2 [list|ls|l|status]
列出指定进程的详细信息:
$ pm2 describe 0
Automatic restart process based on memory
Value passed is in megaoctets. Internally it uses the V8 flag --max-old-space-size=MEM
to make a process exit when memory exceed a certain amount of RAM used.
CLI:
$ pm2 start big-array.js --max-memory-restart 20M
JSON:
{
"name" : "max_mem",
"script" : "big-array.js",
"max_memory_restart" : "20M"
}
Units can be K(ilobyte), M(egabyte), G(igabyte).
监控CPU/内存使用率
监控启动的所有进程:
$ pm2 monit
日志管理
启用pm2.log
的时间戳前缀
export PM2_LOG_DATE_FORMAT="YYYY-MM-DD HH:mm Z"
If this env-variable has been changed, you need to dump your processes and kill daemon, restart it again to take effect, e.g.:
$ pm2 dump
$ pm2 [resurrect|save]
实时显示日志
Displaying logs of specified process or all processes in realtime:
$ pm2 logs
$ pm2 logs big-api
$ pm2 flush # Clear all the logs
高级日志接口
Navigate between processes logs in realtime with an ergonomic interface:
$ pm2 ilogs
重载所有日志 (SIGUSR2/Logrotate)
To reload all logs, you can send SIGUSR2
to the PM2 process.
You can also reload all logs via the command line with:
$ pm2 reloadLogs
选项
--merge-logs : merge logs from different instances but keep error and out separated
--log-date-format <format>: prefix logs with formated timestamp (http://momentjs.com/docs/#/parsing/string-format/)
合并 out
和 err
日志
If you only want to merge
out
anderr
logs into one output file, try with the following examples:$ pm2 start name.js -o name.log -e name.log
{ "apps" : [{ "name" : "name", "script" : "name.js", "err_file" : "name.log", "out_file" : "name.log" }] }
How about merge
out
anderr
logs into one, and also keep the separated logs? e.g.:$ pm2 start -l
$ pm2 start -l name.log
{ "apps" : [{ "name" : "name", "script" : "name.js", "log_file" : true }] }
{ "apps" : [{ "name" : "name", "script" : "name.js", "log_file" : "name.log" }] }
Notes: When you providing a Boolean (
true
) value for-l, --log
option orlog_file
property, it means a merged log file will be automatic generated, i.e.~/.pm2/logs/[name]-[id].log
, otherwise it's specific.
集群 (cluster_mode)
The cluster_mode will automatically wrap your Node.js app into the cluster module and will enable you to reload your app without downtime and to scale your processes across all CPUs available.
To enable the cluster_mode, just pass the -i
$ pm2 start app.js -i 1
To launch max
instances (max
depending on the number of CPUs available) and set the load balancer to balance queries among process:
$ pm2 start app.js --name "API" -i 0
DEPRECATED (STILL COMPATIBLE):
$ pm2 start app.js --name "API" -i max
If your app is well-designed (stateless) you'll be able to process many more queries.
Important concepts to make a Node.js app stateless:
- Sessions must not be stored in memory but shared via a database (Redis, Mongo, whatever)
- WebSocket/Socket.io should communicate via a database
热重载
As opposed to restart
, which kills and restarts the process, reload
achieves a 0-second-downtime reload.
Warning This feature only works for apps in cluster_mode, that uses HTTP/HTTPS/Socket connections.
重载应用:
$ pm2 reload api
If the reload system hasn't managed to reload your app, a timeout will simply kill the process and will restart it.
优雅重载
Sometimes you can experience a very long reload, or a reload that doesn't work (fallback to restart).
It means that your app still has open connections on exit.
To work around this problem you have to use the graceful reload.
Graceful reload is a mechanism that will send a shutdown message to your process before reloading it.
You can control the time that the app has to shutdown via the PM2_GRACEFUL_TIMEOUT
environment variable.
Example:
process.on('message', function(msg) {
if (msg == 'shutdown') {
// Your process is going to be reloaded
// You have to close all database/socket.io/* connections
console.log('Closing all connections...');
// You will have 4000ms to close all connections before
// the reload mechanism will try to do its job
setTimeout(function() {
console.log('Finished closing connections');
// This timeout means that all connections have been closed
// Now we can exit to let the reload mechanism do its job
process.exit(0);
}, 1500);
}
});
Then use the command:
$ pm2 gracefulReload [all|name]
When PM2 starts a new process to replace an old one, it will wait for the new process to begin listening to a connection or a timeout before sending the shutdown message to the old one. You can define the timeout value with the PM2_GRACEFUL_LISTEN_TIMEOUT
environamente variable. I f a script does not need to listen to a connection, it can manually tell PM2 that the process has started up by calling process.send('online')
.
启动脚本
PM2 has the amazing ability to generate startup scripts and configure them. PM2 is also smart enough to save all your process list and to bring back all your processes on restart.
$ pm2 startup [ubuntu|centos|gentoo|systemd]
Once you have started the apps and want to keep them on server reboot do:
$ pm2 save
Warning It's tricky to make this feature work generically, so once PM2 has setup your startup script, reboot your server to make sure that PM2 has launched your apps!
更多信息
Three types of startup scripts are available:
- SystemV init script (with the option
ubuntu
orcentos
) - OpenRC init script (with the option
gentoo
) - SystemD init script (with the
systemd
option)
The startup options are using:
- ubuntu will use
updaterc.d
and the scriptlib/scripts/pm2-init.sh
- centos will use
chkconfig
and the scriptlib/scripts/pm2-init-centos.sh
- gentoo will use
rc-update
and the scriptlib/scripts/pm2
- systemd will use
systemctl
and the scriptlib/scripts/pm2.service
用户权限
Let's say you want the startup script to be executed under another user.
Just use the -u <username>
option !
$ pm2 startup ubuntu -u www
相关命令
Dump all processes status and environment managed by PM2:
$ pm2 dump
It populates the file ~/.pm2/dump.pm2
by default.
To bring back the latest dump:
$ pm2 [resurrect|save]
监控 & 重启
PM2 can automatically restart your app when a file changes in the current directory or its subdirectories:
$ pm2 start app.js --watch
If --watch
is enabled, stopping it won't stop watching:
pm2 stop 0
'll not stop watchingpm2 stop --watch 0
'll stop watching
Restart toggle the watch
parameter when triggered.
To watch specific paths, please use a JSON app declaration, watch
can take a string or an array of paths. Default is true
:
{
"watch": ["server", "client"],
"ignoreWatch" : ["node_modules", "client/img"]
}
JSON app 声明
You can define parameters for your apps in processes.json
:
{
"apps" : [{
"name" : "echo",
"script" : "examples/args.js",
"args" : "['--toto=heya coco', '-d', '1']",
"log_date_format" : "YYYY-MM-DD HH:mm Z",
"ignoreWatch" : ["[\\/\\\\]\\./", "node_modules"],
"watch" : true,
"node_args" : "--harmony",
"cwd" : "/this/is/a/path/to/start/script",
"env": {
"NODE_ENV": "production",
"AWESOME_SERVICE_API_TOKEN": "xxx"
}
},{
"name" : "api",
"script" : "./examples/child.js",
"instances" : "4",
"log_date_format" : "YYYY-MM-DD",
"log_file" : "./examples/child.log",
"error_file" : "./examples/child-err.log",
"out_file" : "./examples/child-out.log",
"pid_file" : "./examples/child.pid",
"exec_mode" : "cluster_mode",
"port" : 9005
},{
"name" : "auto-kill",
"script" : "./examples/killfast.js",
"min_uptime" : "100",
"exec_mode" : "fork_mode"
}]
}
Then run:
$ pm2 start processes.json
$ pm2 stop processes.json
$ pm2 delete processes.json
$ pm2 restart processes.json
A few notes about JSON app declarations:
- All command line options passed when using the JSON app declaration will be dropped i.e.
$ cat node-app-1.json
{
"name" : "node-app-1",
"script" : "app.js",
"cwd" : "/srv/node-app-1/current"
}
JSON app declarations are additive. Continuing from above:
$ pm2 start node-app-2.json $ ps aux | grep node-app root 14735 5.8 1.1 752476 83932 ? Sl 00:08 0:00 pm2: node-app-1 root 24271 0.0 0.3 696428 24208 ? Sl 17:36 0:00 pm2: node-app-2
Note that if you execute
pm2 start node-app-2
again, it will spawn an additional instance node-app-2.cwd: your JSON declaration does not need to reside with your script. If you wish to maintain the JSON(s) in a location other than your script (say,
/etc/pm2/conf.d/node-app.json
) you will need to use the cwd feature. (Note, this is especially helpful for capistrano style directory structures that use symlinks.) Files can be either relative to the cwd directory, or absolute (example below.)The following are valid options for JSON app declarations:
[{ "name" : "node-app", "cwd" : "/srv/node-app/current", "args" : "['--toto=heya coco', '-d', '1']", "script" : "bin/app.js", "node_args" : ["--harmony", " --max-stack-size=102400000"], "log_date_format" : "YYYY-MM-DD HH:mm Z", "error_file" : "/var/log/node-app/node-app.stderr.log", "out_file" : "log/node-app.stdout.log", "pid_file" : "pids/node-geo-api.pid", "instances" : 6, //or 0 => 'max' "min_uptime" : "200s", // 200 seconds, defaults to 1000 "max_restarts" : 10, // defaults to 15 "max_memory_restart": "1M", // 1 megabytes, e.g.: "2G", "10M", "100K", 1024... the default unit is byte. "cron_restart" : "1 0 * * *", "watch" : false, "ignoreWatch" : ["[\\/\\\\]\\./", "node_modules"], "merge_logs" : true, "exec_interpreter" : "node", "exec_mode" : "fork", "env": { "NODE_ENV": "production", "AWESOME_SERVICE_API_TOKEN": "xxx" } }]