Systemd使用

Systemd是Linux操作系统的系统和服务管理器,用来启动守护进程。目前多数Linux发行版都已经采用Systemd取代了initd,作为整个系统的守护进程,成为系统第一个进程(PID为1,其他进程都是他的子进程)。他的设计目的是为了让进程并发启动,按需启动进程,提高Linux系统启动速度,让使用也更简洁。

Systemd跟initd的使用对比:

# initd使用
/etc/init.d/nginx start
# 或
service nginx start
# systemd使用
systemctl start nginx

systemctl命令

systemctl命令是Systemd中最重要的一个命令,用于对进程进行启动,停止等管理操作。

命令格式

systemctl [command] [unit]

例如:

systemctl start nginx.service
# 或
systemctl start nginx

command 说明

start             开启
stop              关闭
restart           重启
status            查看状态
is-active         查看激活与否
enable            设置开机启动
disable           禁止开机启动
is-enabled        查看是否开机自动启动
kill              杀死进程
mask              禁止自动和手动启动
unmask            取消禁止
list-dependencies 查看服务的依赖关系

常用管理命令

# 立即启动
systemctl start nginx.service
# 立即停止
systemctl stop nginx.service
# 重启
systemctl restart nginx.service
# 显示一个Unit的状态
systemctl status nginx.service
# 显示系统状态
systemctl status
# 重新加载一个Unit的配置文件
systemctl reload nginx.service
# 重载所有修改过的配置文件
systemctl daemon-reload
# 列出正在运行的Unit
systemctl list-units # 可以直接使用systemctl
# 列出所有Unit,包括没有找到配置文件的或者启动失败的
systemctl list-units --all
# 列出所有没有运行的 Unit
systemctl list-units --all --state=inactive
# 列出所有加载失败的 Unit
systemctl list-units --failed
# 列出所有正在运行的、类型为service的Unit
systemctl list-units --type=service
# 显示某个 Unit 是否正在运行
systemctl is-active nginx.service
# 显示某个 Unit 是否处于启动失败状态
systemctl is-failed nginx.service
# 显示某个 Unit 服务是否建立了启动链接
systemctl is-enabled nginx.service
# 显示一个 Unit 的所有依赖
systemctl list-dependencies

对Unit操作时,如果缺省扩展名,默认使用.service

Unit

Unit 是 Systemd 管理系统资源的基本单位。Systemd将所有系统资源划分为12类,既有12种 Unit。

  • Service Unit 系统服务,最常见的 Unit
  • Target Unit 多个 Unit 构成的一个组
  • Device Unit 硬件设备
  • Mount Unit 文件系统的挂载点
  • Automount Unit 自动挂载点
  • Path Unit 文件或路径
  • Scope Unit 不是由 Systemd 启动的外部进程
  • Slice Unit 进程组
  • Snapshot Unit Systemd 快照,可以切回某个快照
  • Socket Unit 进程间通信的 socket
  • Swap Unit swap 文件
  • Timer Unit 定时器

Unit 配置文件

每一个 Unit 都有一个配置文件,用来告诉 Systemd 如何管理这个 Unit。配置文件目录默认为/etc/systemd/system/,不过默认目录下存放的多是链接文件,链接到的文件目录为/usr/lib/systemd/system/

Unit 配置文件由三段组成:

  • [Unit] 段:所有类型Unit文件通用,用于提供unit的描述信息、unit行为及依赖关系等
  • [Install] 段:所有类型Unit文件通用,用来定义如何启动,以及是否开机启动
  • [Service] 段:Service Unit文件特有,用于定义服务的具体管理和执行动作

[Unit] 段配置项

  • Description 当前服务的简单描述
  • Documentation 文档地址,可以是一个或多个文档的 URL 路径
  • After 该字段指定的 Unit 全部启动完成以后,才会启动当前 Unit
  • Before 该字段指定的 Unit 必须在当前 Unit 启动完成之后再启动
  • Requires 与其它 Unit 的强依赖关系,如果其中任意一个 Unit 启动失败或异常退出,当前 Unit 也会被退出
  • Wants 与其它 Unit 的弱依赖关系,如果其中任意一个 Unit 启动失败或异常退出,不影响当前 Unit 继续执行
  • Conflicts 定义 Units 间的冲突关系

[Install] 段配置项

  • WantedBy 被哪些 units 所依赖,弱依赖
  • RequiredBy 被哪些 units 所依赖,强依赖
  • Alias 当前 Unit 可用于启动的别名
  • Also 当前 Unit 被 enable/disable 时,会被同时操作的其他 Unit

[Install]段一般设置为 WantedBy=multi-user.target

[Service] 段配置项

  • User 指定运行服务的用户

  • Group 指定运行服务的用户组

  • PIDFile 指向当前服务 PID file 的绝对路径

  • EnvironmentFile 指定当前服务的环境参数文件

  • ExecStart 启动当前服务的命令

  • ExecStartPre 启动当前服务之前执行的命令

  • ExecStartPost 启动当前服务之后执行的命令

  • ExecReload 重启当前服务时执行的命令

  • ExecStop 停止当前服务时执行的命令

  • ExecStopPost 停止当前服务之后执行的命令

  • RemainAfterExit 当前服务的所有进程都退出的时候,Systemd 仍认为该服务是激活状态

  • TimeoutSec 定义 Systemd 停止当前服务之前等待的秒数

  • RestartSec Systemd 重启当前服务间隔的秒数

  • KillMode 定义 Systemd 如何停止服务,可选值:control-group(默认)、process、mixed、none

  • Restart 定义何种情况 Systemd 会自动重启当前服务,可选值:no(默认)、on-success、on-failure、on-abnormal、on-abort、on-watchdog、always

  • Type 定义启动时的进程行为,可选值:

    • simple 默认值,ExecStart字段启动的进程为主进程

    • forking 使ExecStart字段以fork()方式从父进程创建子进程启动,创建后父进程会立即退出,子进程成为主进程。

    • oneshot 只执行一次,Systemd 会等当前服务退出,再继续往下执行

    • dbus 当前服务通过 D-Bus 信号启动。当指定的 BusName 出现在 DBus 系统总线上时,Systemd认为服务就绪

    • notify 当前服务启动完毕会发出通知信号,通知 Systemd,然后 Systemd 再启动其他服务

    • idle Systemd 会等到其他任务都执行完,才会启动该服务

使用实例:systemctl托管Golang项目

创建文件 /etc/systemd/system/xxx.service 编辑内容如下:

[Unit]
Description=XXX # XXX为应用名称
After=syslog.target network-online.target

[Service]
Type=simple
WorkingDirectory=/data/xxx/ # /data/xxx/为运行目录
ExecStart=./xxx # xxx为可执行程序
Restart=always
RestartSec=2s

[Install]
WantedBy=multi-user.target

如果需要将程序输出重定向到文件,可以采用如下方式

[Unit]
Description=XXX # XXX为应用名称
After=syslog.target network-online.target

[Service]
Type=simple
WorkingDirectory=/data/xxx/ # /data/xxx/为运行目录
ExecStart=/bin/sh -c 'exec ./xxx >> run.log 2>&1' # xxx为可执行程序
Restart=always
RestartSec=2s

[Install]
WantedBy=multi-user.target

Systemd的其他命令

除了systemctl,Systemd还包含一些其他系统管理的命令:

systemd-analyze 查看系统启动耗时

hostnamectl 查看当前主机的信息

localectl 查看本地化设置

timedatectl 查看当前时区设置

loginctl 查看当前登录用户

journalctl 系统日志管理

journalctl 命令管理Unit日志

Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf

常用日志管理命令

# 查看所有日志(默认只保存本次启动的日志)
journalctl
# 查看内核日志(不显示应用日志)
journalctl -k
# 查看系统本次启动的日志
journalctl -b
journalctl -b -0
# 查看上一次启动的日志(需更改设置)
journalctl -b -1
# 查看指定时间的日志
journalctl --since="2012-10-30 18:17:16"
journalctl --since "20 min ago"
journalctl --since yesterday
journalctl --since "2015-01-10" --until "2015-01-11 03:00"
journalctl --since 09:00 --until "1 hour ago"
# 显示尾部的最新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
# 查看某个 Unit 的日志
journalctl -u nginx.service
journalctl -u nginx.service --since today
# 实时滚动显示某个 Unit 的最新日志
journalctl -u nginx.service -f
# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today
# 日志默认分页输出,--no-pager 改为正常的标准输出
journalctl --no-pager
# 以 JSON 格式(单行)输出
journalctl -b -u nginx.service -o json
# 以 JSON 格式(多行)输出,可读性更好
journalctl -b -u nginx.serviceqq -o json-pretty
# 显示日志占据的硬盘空间
journalctl --disk-usage
# 指定日志文件占据的最大空间
journalctl --vacuum-size=1G
# 指定日志文件保存多久
journalctl --vacuum-time=1years