最近想把nodejs 的服务器作为服务随linux启动而启动。发现对这部分理解并不是非常清晰,这里重新整理学习一下这部分内容。

1 服务的概念

在Linux中,服务是在后台运行的程序。服务可以按需启动,也可以在启动时启动。

如果您使用Linux作为主要操作系统或开发平台,那么您将处理不同的服务,例如webserver,ssh或cron。在调试系统问题时,了解如何列出正在运行的服务或检查服务状态非常重要。

最近的大多数Linux发行版都使用systemd作为默认的初始化系统和服务管理器。

Systemd是一套用于管理Linux系统的工具。它用于启动计算机,管理服务,自动挂载文件系统,日志事件,设置主机名和其他系统任务。

Systemd使用unit的概念,可以是services, mount points, devices等类型。使用ini格式定义的文本文件来定义单元。这些文件包括有关设备,其设置和要执行的命令的信息。文件扩展名定义单元文件类型。例如,.mount文件定义了一个挂载点, 系统service unit文件具有.service扩展名,等等。

systemctl是一个命令行实用程序,用于控制systemd和管理服务。它是systemd生态系统的一部分,默认情况下在所有系统上都可用。

1.1 查看服务列表

我们可以使用sudo systemctl list-units --type service查看已经加载的服务unit列表

sudo systemctl list-units --type service
输出;
UNIT                            LOAD   ACTIVE SUB     DESCRIPTION
  accounts-daemon.service         loaded active running Accounts Service
  acpid.service                   loaded active running ACPI event daemon
  apparmor.service                loaded active exited  LSB: AppArmor initialization
  apport.service                  loaded active exited  LSB: automatic crash report gene

输出的每一行从左到右包含以下几列:

  • UNIT -服务Unit的名称。
  • LOAD -有关unit文件是否已加载到内存中的信息。
  • ACTIVE-高级unit文件激活状态,可以是活动,重新加载,非活动,失败,激活,停用。它是该SUB列的概括。
  • SUB-低级单位文件激活状态。该字段的值取决于单位类型。例如,类型服务单元可以处于下列状态之一:死,退出,失败,不活动或正在运行。
  • DESCRIPTION` -unit文件的简短描述。

1.2 查看具体服务状态

sudo systemctl status <service_name>.service

<service_name>您要检查的服务单元的名称在哪里,我们也可以省略service参数。例如,要确定nginx服务的当前状态,请运行:

sudo systemctl status nginx

输出

● 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 2021-01-21 17:07:32 CST; 47min ago
     Docs: man:nginx(8)
  Process: 628 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 466 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 631 (nginx)
    Tasks: 2 (limit: 1130)
   CGroup: /system.slice/nginx.service
           ├─631 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           └─634 nginx: worker process

Jan 21 17:07:32 iZ8vbiie7niq2hbvvjlsrkZ systemd[1]: Starting A high performance web server and a reverse proxy server...
Jan 21 17:07:32 iZ8vbiie7niq2hbvvjlsrkZ systemd[1]: nginx.service: Failed to parse PID from file /run/nginx.pid: Invalid argument
Jan 21 17:07:32 iZ8vbiie7niq2hbvvjlsrkZ systemd[1]: Started A high performance web server and a reverse proxy server.
  • Loaded-服务unit是否已加载以及unit文件的完整路径。它还显示是否开机启动(enabled 表示开机时启动)。
  • Active-服务是否处于活动状态并正在运行。如果您的终端支持颜色,并且该服务已启用并且正在运行,则点()和“活动(正在运行)”部分将以绿色打印。该行还显示了服务运行了多长时间。active (running) 表示服务正在运行中。如果是 inactive (dead) 则表示服务当前没有运行
  • Docs -服务文档。
  • Process -有关服务流程的信息。
  • Main PID -服务PID。
  • Tasks -占单位的任务数和任务限制。
  • Memory -有关已用内存的信息。
  • CGroup -有关控制组的信息。

1.3 自启动service文件编写

相关service 文件位置存放在 systemd的Unit放在目录

  • /usr/lib/systemd/system(Centos)
  • /etc/systemd/system(Ubuntu 系统service) 或 /lib/systemd/system/ (应用services)

.service文件定义了一个服务,分为[Unit],[Service],[Install]三个小节

[Unit]
Description:描述,
After:在network.target,auditd.service启动后才启动
ConditionPathExists: 执行条件
[Service]
EnvironmentFile:变量所在文件
ExecStart: 执行启动脚本
Restart: fail时重启
[Install]
Alias:服务别名
WangtedBy: 多用户模式下需要的

我们可以看一下nginx 的service文件样例

# 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

所以我们可以参照这个样例编写一个我们需要自启动的服务的service。比如我要想要启动egg 服务器

[Unit]
Description=node egg server
After=network.target

[Service]
Type=forking
WorkingDirectory=/home/ubuntu/egg
ExecStart=/usr/local/bin/npm start
ExecStop=/usr/local/bin/npm stop
TimeoutStopSec=30
KillMode=mixed
User=ubuntu
Group=ubuntu

[Install]
WantedBy=multi-user.target

然后保存到这个目录下 vi /lib/systemd/system/egg.service

sudo systemctl daemon-reload # 加载新的service文件
sudo systemctl start egg
sudo systemctl status egg

我们可以看到以下属性:

Active: active (running) since Fri 2021-01-22 03:24:36 UTC; 25s ago

2 systemctl 命令集合

管理命令

sudo systemctl list-units --type=service # 显示所有已启动的服务
sudo systemctl list-units --type service --all #查看已加载但无效的服务
sudo systemctl list-unit-files #所有已安装的unit文件,而不仅仅是加载的服务
sudo systemctl reboot  # 重新开机
sudo systemctl poweroff # 系统关机

针对某个具体服务的命令:

systemctl start nfs-server.service    # 启动nfs服务
systemctl enable nfs-server.service   # 设置开机自启动
systemctl disable nfs-server.service  # 停止开机自启动
systemctl status nfs-server.service   # 查看服务当前状态
systemctl restart nfs-server.service  # 重新启动某服务