在程序开发中我们必不可少要与服务器打交道,如果做后端开发,更需要了解服务器的进程运行方式,并且能够实现守护进程的实现
在 Node.js 的项目中,我们通常会使用 pm2 来作为 Node.js 的守护进行,比如 pm2 list 查看已运行的守护进程列表,使用 pm2 start index.js --name server 来添加新的 Node.js 进程到 pm2 的进程池中
当然我们也可以使用系统级别的守护进程,像使用 Nginx Apache 等软件,通过使用 systemctl 来管理系统进程
比如查看 Nginx 的进程状态
systemctl status nginx
# output
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-12-17 02:16:33 UTC; 2 weeks 6 days ago
Docs: man:nginx(8)
Main PID: 609 (nginx)
Tasks: 3 (limit: 4713)
Memory: 11.5M
CGroup: /system.slice/nginx.service
├─609 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
├─610 nginx: worker process
└─611 nginx: worker process
Dec 17 02:16:26 hongkong-morgon systemd[1]: Starting A high performance web server and a reverse proxy server...
Dec 17 02:16:33 hongkong-morgon systemd[1]: Started A high performance web server and a reverse proxy server.
使用系统级别的守护进程需要添加 service 文件
什么是 service 文件
在了解 service 之前,需要先知道什么是 systemd ,service 文件是 systemd 运行时的配置文件
查看 Nginx 运行时配置文件
systemctl cat nginx.service
# output
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
从输出结果可以看出配置文件主要分为三个部分 [Unit] [Service] [Install] ,每一部分都是以等号连接的键值对,中间不能有额外的空格。
配置参数
[Unit]
[Unit] 区块主要是配置 service 的描述,以及与其他的 Service 的关系
Description:简短描述Documentation:文档地址Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行Condition...:当前 Unit 运行必须满足的条件,否则不会运行Assert...:当前 Unit 运行必须满足的条件,否则会报启动失败
[Service] 区块在守护进程的类型为 Service 时才存在,该区块主要配置 Service 的运行时参数以及行为
-
Type:定义启动时的进程行为。它有以下几种值。-
Type=simple:默认值,执行ExecStart指定的命令,启动主进程 -
Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出 -
Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行 -
Type=dbus:当前服务通过D-Bus启动 -
Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行 -
Type=idle:若有其他任务执行完毕,当前服务才会运行
-
-
ExecStart:启动当前服务的命令 -
ExecStartPre:启动当前服务之前执行的命令 -
ExecStartPost:启动当前服务之后执行的命令 -
ExecReload:重启当前服务时执行的命令 -
ExecStop:停止当前服务时执行的命令 -
ExecStopPost:停止当其服务之后执行的命令 -
RestartSec:自动重启当前服务间隔的秒数 -
Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog -
TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数 -
Environment:指定环境变量
[Install] 通常是配置文件的最后一个区块,定义服务的启动、重启、关闭的行为
WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 +.wants后缀构成的子目录中RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 +.required后缀构成的子目录中Alias:当前 Unit 可用于启动的别名Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit
Unit 配置文件的完整字段清单,请参考官方文档
实战
以下是在 Root 用户目录下 添加一个脚本输出当前时间,并添加执行权限
#!/usr/bin/bash
# output current time per 5 second
function main() {
while :
do
echo $(date)
sleep 5
done
}
main
chmod +x now
执行测试
now
# output
Wed Jan 6 17:30:16 CST 2021
添加 Service 文件
vim nowd.service
添加 Service 内容
[Unit]
Description=now
[Service]
ExecStart=/usr/local/bin/now
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
Restart=always
[Install]
WantedBy=default.target
将命令 now 和 Service 文件软连接到系统的 systemd 配置文件目录
# link now script to /usr/local/bin directory
ln -s /root/now /usr/local/bin/now
# link service file to systemd config directory
ln -s /root/nowd.service /usr/lib/systemd/system/nowd.service
将配置文件添加到系统配置目录中之后通过执行 systemctl cat nowd.service 查看是否链接成功
systemctl cat nowd.service
# output
# /root/nowd.service
[Unit]
Description=now
[Service]
ExecStart=/usr/local/bin/now
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
Restart=always
[Install]
WantedBy=default.target
然后通过 systemctl 命令执行守护进程,并查看执行状态
# start now daemon
systemctl start nowd.service
# view now daemon status
systemctl status nowd.service
# stop now daemon status
systemctl stop nowd.service
我们可以通过查看进程的日志来查看输出的日志
journalctl -f
# output
1月 06 17:29:01 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:01 CST 2021
1月 06 17:29:06 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:06 CST 2021
1月 06 17:29:11 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:11 CST 2021
1月 06 17:29:16 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:16 CST 2021
1月 06 17:29:21 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:21 CST 2021
1月 06 17:29:26 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:26 CST 2021
1月 06 17:29:31 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:31 CST 2021
1月 06 17:29:36 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:36 CST 2021
1月 06 17:29:41 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:41 CST 2021
1月 06 17:29:46 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:46 CST 2021
1月 06 17:29:51 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:51 CST 2021
1月 06 17:29:56 iz2zeacp86oa3gdr655z7oz now[28375]: Wed Jan 6 17:29:56 CST 2021
可以看到系统守护进行在每 5 秒即执行一次 now 的命令
更多内容
更多的内容请关注GitHub,知乎@大手印,或者关注我的公众号@全栈开发师,我会不定时分享一些全栈方向的开发内容,谢谢分享

本文详细介绍了如何在Node.js项目中使用pm2作为守护进程,以及如何通过systemd管理Nginx等系统级守护进程。涵盖了service文件配置、实战步骤和关键配置参数的解读。
1844

被折叠的 条评论
为什么被折叠?



