Systemd 从入门到实战
前言
本文主要包含内容如下:
-
Systemd
是什么? -
Systemd
常用命令。 -
Systemd
系统资源Unit
(单位)。 -
Systemd
系统资源管理 - 动手配置,实现开机自启动 Node.js 服务。
一,Systemd 概述
1.1. 基本介绍
Systemd (System Daemon)
,根据 Linux 命名惯例,字母 d
是守护进程 daemon
的缩写。如 Systemd
名字的含义一样,它作为 PID 1
进程,守护整个系统。Systemd
是一系列工具的集合,其作用也远远不仅是启动操作系统,它还接管了后台服务、结束、状态查询,以及日志归档、设备管理、电源管理、定时任务等许多职责。
systemd
由 Lennart Poettering 带头开发,并在 LGPL 2.1
及其后续版本许可证下开源发布。systemd
已纳入众多 Linux 发行版的软件源中。
1.2. 特点介绍
缺点是体系庞大,非常复杂。
Systemd
的优点是功能强大,使用方便。其优点介绍如下:
更少的进程
Systemd
提供了服务按需启动的能力。允许更多的进程并行启动
在SysV-init
时代,将每个服务项目编号依次执行启动脚本。而Systemd
通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。使用
CGroup
跟踪和管理进程的生命周期Systemd
提供通过CGroup
跟踪进程关系。CGroup
不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期。统一管理服务日志
Systemd
提供了一个专用的系统日志管理服务:Journald
。其使用二进制格式保存所有的日志信息,因而日志内容很难被手工伪造。
1.3. 架构图
下图 是 Systemd
的架构图(来自网络)
二,Systemd 常用命令
Systemd
并不是一个命令,而是一组命令,涉及到系统管理的方方面面,是一系列工具的集合。
2.1. systemctl
systemctl
是 Systemd
的主要命令,用于系统与服务管理。点击查看命令描述文档
命令语法
$ systemctl [OPTIONS...] COMMAND [UNIT...]
常用命令
下述命令以 Unitnginx.service
为列,后续会详细介绍 Unit。# 重启系统 $ systemctl reboot # 启用一个或多个单元或单元实例 $ systemctl enable nginx.service # 禁用一个或多个单位 $ systemctl disable nginx.service # 重新启用一个或多个单位 $ systemctl reenable nginx.service # 重新载入 unit 配置 $ systemctl daemon-reload # 启动 unit 资源 $ systemctl start nginx.service # 重启一个服务 $ systemctl restart nginx.service # 重新加载一个服务的配置文件 $ systemctl reload nginx.service # 停止 unit 资源 $ systemctl stop nginx.service # 查看 unit 资源 状态 $ systemctl status nginx.service # 杀死一个服务的所有子进程 $ systemctl kill nginx.service # 命令行输出 unit 配置 $ systemctl cat nginx.service # 显示 systemd Manager 环境块 $ systemctl show-environment # 列出 systemd 当前在内存中的 unit $ systemctl list-units # 查看 Unit 存在依赖关系 $ systemctl list-dependencies nginx.service # 显示某个 Unit 的所有底层参数 $ systemctl show nginx.service
2.2. systemd-analyze
systemd-analyze
分析和调试系统管理。点击查看命令描述文档
命令语法
$ systemd-analyze [OPTIONS...] [time] $ systemd-analyze [OPTIONS...] blame $ systemd-analyze [OPTIONS...] critical-chain [UNIT...]
常用命令
# 查看启动耗时 $ systemd-analyze time # 查看每个服务的启动耗时 $ systemd-analyze blame # 显示瀑布状的启动过程流 $ systemd-analyze critical-chain # 显示指定服务的启动流 $ systemd-analyze critical-chain atd.service
2.3. hostnamectl
hostnamectl
可用于查询和更改系统主机名和相关设置。点击查看命令描述文档
命令语法
$ hostnamectl [OPTIONS...] {COMMAND}
常用命令
# 查看主机的信息 $ hostnamectl status # 设置主机名 $ hostnamectl set-hostname york
2.4. journalctl
journalctl
查询系统日志。点击查看命令描述文档
命令语法
$ journalctl [OPTIONS...] [MATCHES...]
常用命令
# 查看所有日志 $ journalctl # 查看指定 unit 日志 $ journalctl _SYSTEMD_UNIT=httpd.service # 查看内核日志(不显示应用日志) $ journalctl -k # 查看系统本次启动的日志 $ journalctl -b $ journalctl -b -0 # 查看上一次启动的日志(需更改设置) $ journalctl -b -1 # 显示尾部的最新10行日志 $ journalctl -n # 显示尾部指定行数的日志 $ journalctl -n 20 # 实时滚动显示最新日志 $ journalctl -f # 查看指定服务的日志 $ journalctl /usr/lib/systemd/systemd # 查看指定进程的日志 $ journalctl _PID=1 # 查看某个路径的脚本的日志 $ journalctl /usr/bin/bash # 查看指定用户的日志 $ journalctl _UID=33 --since today
2.5. loginctl
loginctl
系统登陆管理器。点击查看命令描述文档
命令语法
$ loginctl [OPTIONS...] {COMMAND} [NAME...]
常用命令
# 列出当前登录用户 $ loginctl list-users # 列出显示指定用户的信息 $ loginctl show-user root # 查看 sission 详情 $ loginctl show-session 130423 559 59
2.6. timedatectl
timedatectl
系统时间和日期查看与管理。点击查看命令描述文档
命令语法
$ timedatectl [OPTIONS...] {COMMAND}
常用命令
# 查看当前时区设置 $ timedatectl # 显示所有可用的时区 $ timedatectl list-timezones # 设置当前时区 $ timedatectl set-timezone America/New_York
三,Systemd 资源
Systemd
可以管理所有系统资源。不同的资源统称为Unit
(单位)。
点击查看 systemd.unit 描述文档
点击查看 systemd.service 描述文档
3.1. Unit 种类
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
3.2. Unit 文件结构
下面这个 foo.service
Unit。
# [Unit]区块包含与单元类型无关的通用信息
[Unit]
Description=Foo
# [Service]区块包含服务启动信息
[Service]
ExecStart=/usr/sbin/foo-daemon
# [Install]区块包含单元的启用信息
[Install]
WantedBy=multi-user.target
- 从上面的输出可以看到,配置文件分成几个区块。每个区块的第一行,是用方括号表示的区别名,比如:
[Unit]
- 区块内容
每个区块内部是一些等号连接的键值对。[Service] ExecStart=/usr/sbin/foo-daemon ExecStop=xxx
- 配置文件注释使用
#
开头 - 注意事项
配置文件的区块名和字段名,都是大小写敏感的
键值对的等号两侧不能有空格。
3.3. [Unit] 区块
Unit 文件中的 [Unit] 区块包含与 Unit 类型无关的通用信息。可用的如下配置指令如下:
Description:有利于人类阅读的、对单元进行简单描述的字符串。
Documentation:一组用空格分隔的文档URI列表, 这些文档是对此单元的详细说明。
Requires:设置此单元所必须依赖的其他单元。
Wants:此选项是 Requires= 的弱化版。
BindsTo:与 Requires= 类似,但是依赖性更强
Before, After:强制指定单元之间的先后顺序,接受一个空格分隔的单元列表。
Conflicts:指定单元之间的冲突关系。表明该单元不能与列表中的任何单元共存
3.4. [Service] 区块
[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:指定服务的工作目录
3.5. [Install] 区块
[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 停用 此单元时, 也同时自动的启用或停用附属单元。
3.6. Unit 文件加载
Systemd
将会从一组在编译时设定好的 Unit 目录
中加载单元文件,目录拥有不同的优先级。高优先级目录中的文件, 将会覆盖低优先级目录中的同名文件。
- 当 systemd 以系统实例(–system)运行时,加载单元的先后顺序(较前的目录优先级较高)
系统单元目录 | 描述 |
---|---|
/run/systemd/transient | 动态配置的临时单元(系统与全局用户共用) |
/etc/systemd/system | 本地配置的系统单元 |
/run/systemd/system | 运行时配置的系统单元 |
/usr/lib/systemd/system | 本地软件包安装的系统单元 |
/usr/lib/systemd/system | 发行版软件包安装的系统单元 |
- 当 systemd 以用户实例(–user)运行时,加载单元的先后顺序(较前的目录优先级较高)
系统单元目录 | 描述 |
---|---|
/etc/systemd/user | 本地配置的全局用户单元 |
/run/systemd/user | 运行时配置的全局用户单元 |
/usr/lib/systemd/user | 本地软件包安装的全局用户单元 |
/usr/lib/systemd/user | 发行版软件包安装的全局用户单元 |
3.7. 设置开机启动
可使用
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 资源管理
该节使用 Systemd
管理 Node.js
应用,实现应用的开机自启动。
4.1. 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);
4.2. 配置 Unit
配置 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
4.3. 启动应用
使用 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
4.4. 设置开机启动
使用 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
查看服务状态。
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!