本文主要包含内容如下:
Systemd
是什么?Systemd
常用命令。Systemd
系统资源 Unit
(单位)。Systemd
系统资源管理 - 动手配置,实现开机自启动 Node.js 服务。Systemd (System Daemon)
,根据 Linux 命名惯例,字母 d
是守护进程 daemon
的缩写。如 Systemd
名字的含义一样,它作为 PID 1
进程,守护整个系统。Systemd
是一系列工具的集合,其作用也远远不仅是启动操作系统,它还接管了后台服务、结束、状态查询,以及日志归档、设备管理、电源管理、定时任务等许多职责。
systemd
由 Lennart Poettering 带头开发,并在 LGPL 2.1
及其后续版本许可证下开源发布。systemd
已纳入众多 Linux 发行版的软件源中。
缺点是体系庞大,非常复杂。
Systemd
的优点是功能强大,使用方便。其优点介绍如下:
Systemd
提供了服务按需启动的能力。SysV-init
时代,将每个服务项目编号依次执行启动脚本。而 Systemd
通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。CGroup
跟踪和管理进程的生命周期
Systemd
提供通过 CGroup
跟踪进程关系。CGroup
不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期。Systemd
提供了一个专用的系统日志管理服务:Journald
。其使用二进制格式保存所有的日志信息,因而日志内容很难被手工伪造。下图 是 Systemd
的架构图(来自网络)
Systemd
并不是一个命令,而是一组命令,涉及到系统管理的方方面面,是一系列工具的集合。
systemctl
是 Systemd
的主要命令,用于系统与服务管理。点击查看命令描述文档
命令语法
常用命令
下述命令以 Unit nginx.service
为列,后续会详细介绍 Unit。
systemd-analyze
分析和调试系统管理。点击查看命令描述文档
命令语法
常用命令
hostnamectl
可用于查询和更改系统主机名和相关设置。点击查看命令描述文档
命令语法
常用命令
journalctl
查询系统日志。点击查看命令描述文档
命令语法
常用命令
loginctl
系统登陆管理器。点击查看命令描述文档
命令语法
常用命令
timedatectl
系统时间和日期查看与管理。点击查看命令描述文档
命令语法
常用命令
Systemd
可以管理所有系统资源。不同的资源统称为Unit
(单位)。
点击查看 systemd.unit 描述文档 点击查看 systemd.service 描述文档
Unit
文件是 ini 风格的纯文本文件。统一了过去各种不同系统资源配置格式,例如服务的启/停、定时任务、设备自动挂载、网络配置、虚拟内存配置等。而 Systemd
通过不同的文件后缀(如 .service)来区分这些配置文件。支持的 11 种 Unit
文件类型:
# 服务,封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件
service.service
# 套接字,监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动
socket.socket
# 设备,对于 /dev 目录下的设备,主要用于定义设备之间的依赖关系
device.device
# 挂载点,定义系统结构层次中的一个挂载点,可以替代过去的 /etc/fstab 配置文件
mount.mount
# 自动挂载点,用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务
automount.automount
# 交换分区或交换文件,定义一个用户做虚拟内存的交换分区
swap.swap
# 启动目标,用于对 Unit 文件进行逻辑分组,引导其它 Unit 的执行。它替代了 SysV-init 运行级别的作用,并提供更灵活的基于特定设备事件的启动方式
target.target
# 被监视的路径,用于监控指定目录或文件的变化,并触发其它 Unit 运行
path.path
# 任务计划,用于配置在特定时间触发的任务,替代了 Crontab 的功能
timer.timer
# 资源控制组,用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件
slice.slice
# 一组外部创建的进程,这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息
scope.scope
下面这个 foo.service
Unit。
# [Unit]区块包含与单元类型无关的通用信息
[Unit]
Description=Foo
# [Service]区块包含服务启动信息
[Service]
ExecStart=/usr/sbin/foo-daemon
# [Install]区块包含单元的启用信息
[Install]
WantedBy=multi-user.target
从上面的输出可以看到,配置文件分成几个区块。每个区块的第一行,是用方括号表示的区别名,比如:
区块内容每个区块内部是一些等号连接的键值对。
配置文件注释使用 开头
注意事项配置文件的区块名和字段名,都是大小写敏感的键值对的等号两侧不能有空格。
Unit 文件中的 [Unit] 区块包含与 Unit 类型无关的通用信息。可用的如下配置指令如下:
Description:有利于人类阅读的、对单元进行简单描述的字符串。
Documentation:一组用空格分隔的文档URI列表, 这些文档是对此单元的详细说明。
Requires:设置此单元所必须依赖的其他单元。
Wants:此选项是 Requires= 的弱化版。
BindsTo:与 Requires= 类似,但是依赖性更强
Before, After:强制指定单元之间的先后顺序,接受一个空格分隔的单元列表。
Conflicts:指定单元之间的冲突关系。表明该单元不能与列表中的任何单元共存
[Service]
区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。包含服务启动信息。可用的如下配置指令如下:
Type:设置进程的启动类型。取值为 simple, exec, forking, oneshot, dbus, notify, idle 之一。
RemainAfterExit:当该服务的所有进程全部退出之后, 是否依然将此服务视为活动(active)状态。 默认值为 no
PIDFile:该服务PID文件的路径(一般位于 /run/ 目录下)。 强烈建议在 Type=forking 的情况下明确设置此选项。
BusName:设置与此服务通信 所使用的 D-Bus 名称。
ExecStart:在启动该服务时需要执行的 命令行(命令+参数),命令行必须以一个可执行文件(要么是绝对路径、要么是不含任何斜线的文件名)开始, 并且其后的那些参数将依次作为"argv[1] argv[2] …"传递给被执行的进程。
ExecReload:这是一个可选的指令, 用于设置当该服务 被要求重新载入配置时 所执行的命令行。
ExecStop:这是一个可选的指令, 用于设置当该服务被要求停止时所执行的命令行。
Restart:当服务进程 正常退出、异常退出、被杀死、超时的时候, 是否重新启动该服务。所谓"服务进程" 是指 ExecStartPre=, ExecStartPost=, ExecStop=, ExecStopPost=, ExecReload= 中设置的进程。
Environment:指定环境变量
User:指定运行服务的用户
Group:指定运行服务的用户组
WorkingDirectory:指定服务的工作目录
[Install]
区块包含单元的启用信息。 当执行命令 systemctl enable 与 disable 操作 Unit 时才会使用此小节。
Alias:启用时使用的别名,可以设为一个空格分隔的别名列表。
WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中
RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中
Also:设置此单元的附属单元,表示当使用 systemctl enable 启用 或 systemctl disable 停用 此单元时, 也同时自动的启用或停用附属单元。
Systemd
将会从一组在编译时设定好的 Unit 目录
中加载单元文件,目录拥有不同的优先级。高优先级目录中的文件, 将会覆盖低优先级目录中的同名文件。
系统单元目录 | 描述 |
---|---|
/run/systemd/transient | 动态配置的临时单元(系统与全局用户共用) |
/etc/systemd/system | 本地配置的系统单元 |
/run/systemd/system | 运行时配置的系统单元 |
/usr/lib/systemd/system | 本地软件包安装的系统单元 |
/usr/lib/systemd/system | 发行版软件包安装的系统单元 |
系统单元目录 | 描述 |
---|---|
/etc/systemd/user | 本地配置的全局用户单元 |
/run/systemd/user | 运行时配置的全局用户单元 |
/usr/lib/systemd/user | 本地软件包安装的全局用户单元 |
/usr/lib/systemd/user | 发行版软件包安装的全局用户单元 |
可使用
systemctl enable
命令激活 Unit 开机启动。
Systemd 默认从目录 /etc/systemd/system/
读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/
,真正的配置文件存放在这个目录。
systemctl enable
命令用于在上面两个目录之间,建立符号链接关系。
# 激活开机启动
$ systemctl enable koa.service
# 等同于
$ ln -s '/usr/lib/systemd/system/koa.service' '/etc/systemd/system/multi-user.target.wants/koa.service'
该节使用 Systemd
管理 Node.js
应用,实现应用的开机自启动。
新建文件 /data/app/node.js/node-systemd-demo/app.js
,其内容如下。
const http = require('http');
http.createServer((request, response) => {
response.write('Systemd 从入门到实战');
response.end();
}).listen(8091);
配置 Systemd 的 Unit 文件,用于管理 Node.js 应用。新建文件 /usr/lib/systemd/system/node-demo.service
,其内容如下:
#!/bin/bash
# 服务说明
[Unit]
# 服务描述
Description=node-systemd-demo
# 前置需要启动的服务
After=sysinit.target
# 服务启动行为
[Service]
# 服务类型
Type=simple
ExecStart=/usr/local/services/nodejs/bin/node /data/app/node.js/node-systemd-demo/app.js
# 设置预加载变量
Environment="PATH=/usr/local/services/nodejs/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/.ft:/root/bin"
# 执行用户
User=root
# 执行用户组
Group=root
WorkingDirectory=/data/app/node.js/node-systemd-demo
# 服务开机启动安装目标
[Install]
# 表示该服务所在的 Target
WantedBy=multi-user.targe
使用 Systemd 启动运行 node-demo.service
,执行下命令:
# 设置可执行权限
$ chmod +x /usr/lib/systemd/system/node-demo.service
# 重新载入 Unit 配置
$ systemctl daemon-reload
# 启动 Unit 服务
$ systemctl start node-demo.service
# 查看 Unit 服务状态
$ systemctl status node-demo.service
# 请求 node-systemd-demo 服务
$ curl -v http://127.0.0.1:8091
使用 Systemd 配置 node-demo.service
服务开机启动,执行下命令:
# 激活开机启动
$ systemctl enable node-demo.service
# 或者 ln 激活开机启动
ln -s /usr/lib/systemd/system/node-demo.service /etc/systemd/system/multi-user.target.wants/
# 重启 linux
$ reboot
激活开机启动后,会在 /etc/systemd/system/multi-user.target.wants/
目录中添加 node-demo.service
软链接。
执行 reboot
后,执行命令 systemctl status node-demo.service
查看服务状态。