Linux systemctl 详解&自定义 systemd unit

Posted 青冬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux systemctl 详解&自定义 systemd unit相关的知识,希望对你有一定的参考价值。

Linux systemctl 详解&自定义 systemd unit

systemctl

大家都知道,我们安装了很多服务之后,使用 systemctl 来管理这些服务,比如开启、重启、关闭等等,所以 systemctl 是一个 systemd 系统。centos 使用 systemctl 来代替 daemon chkconfig,原来的所有系统启动和管理系统服务全部由 systemctl 来代替。

systemctl 命令

我们可以查看官方给出的命令:

systemctl --help

可以看到 systemctl 包含两类命令, OPTIONSCOMMANDOPTIONS- 开头,而 COMMAND 则不会。

行头

如果我们直接执行 systemctl,则会打印

systemctl

可以看到行头为:

UNIT

UNIT 是统一了各种不同系统资源的配置格式,列如服务器的启停、定时任务、设备挂载、网络配置、虚拟内存等等。通过不同的后缀来区分这些配置文件。

包含 12 类:

LOAD

systemd 是否正确解析了单元的配置并将该单元加载到内存中。

loaded 表示成功加载到内存中,没有问题。

ACTIVE

高级单元激活状态。

The low-level unit activation state, values depend on unit type.

active 表示成功激活。

failed 表示激活失败。

SUB

低级单元激活状态。

The low-level unit activation state, values depend on unit type.

active 表示成功激活。

failed 表示激活失败。

DESCRIPTION

对该 unit 的一些描述。

OPTIONS

由于命令太多,只演示一些重要、常用的:

-t --type=TYPEList units of a particular type
–state=STATEList units with particular LOAD or SUB or ACTIVE state
-p --property=NAMEShow only properties by this name
-a --allShow all loaded units/properties, including dead/empty ones. To list all units installed on the system, use the ‘list-unit-files’ command instead.
-l --fullDon’t ellipsize unit names on output
-r --recursiveShow unit list of host and local containers
–reverseShow reverse dependencies with ‘list-dependencies’
–job -mode=MODESpecify how to deal with already queued jobs, when queueing a new job
–show-typesWhen showing sockets, explicitly show their type
-i --ignore-inhibitorsWhen shutting down or sleeping, ignore inhibitors
–kill-who=WHOWho to send signal to
-s --signal=SIGNALWhich signal to send
–nowStart or stop unit in addition to enabling or disabling it
-q --quietSuppress output
–no-blockDo not wait until operation finished
–no-wallDon’t send wall message before halt/power-off/reboot
–no-reloadDon’t reload daemon after en-/dis-abling unit files
–no-legendDo not print a legend (column headers and hints)
–no-pagerDo not pipe output into a pager
–no-ask-passwordDo not ask for system passwords
–globalEnable/disable unit files globally
–runtimeEnable unit files only temporarily until next reboot
-f --forceWhen enabling unit files, override existing symlinks When shutting down, execute action immediately
–preset-mode=Apply only enable, only disable, or all presets
–root=PATHEnable unit files in the specified root directory
-n --lines=INTEGERNumber of journal entries to show
-o --output=STRINGChange journal output mode (short, short-iso, short-precise, short-monotonic, verbose, export, json, json-pretty, json-sse, cat)
–plainPrint unit dependencies as a list instead of a tree

-t --type=TYPE

根据 UNIT 的 12 种类型来筛选,比如找出为 UNIT 为 service 类型:

systemctl --type=service # 所有服务的运行状态,但不包含系统服务

–state=ACTIVE

根据 state 进行筛选,如筛选运行中的:

systemctl --state=active --type=service

当然可以复合筛选,比如运行中的服务:

systemctl --state=active --type=service

COMMAND

mask 屏蔽服务

将服务进行屏蔽后,就无法通过 systemctl 来进行各种管理,如:

systemctl mask firewalld

可以看到,在 mask 之前是 loaded 状态,但是在之后就变成了 masked 状态,而且现在无法操控:

必须手动取消屏蔽,才可以继续操控(这里操控其实是启动,停止不收影响):

systemctl unmask firewalld
systemctl start firewalld

enable 开机启动

如果我们想将一个服务开机启动,那么我们可以:

systemctl enable chronyd
systemctl is-enabled chronyd # 查看是否设置了开机启动

关闭开机启动也很简单:

systemctl disable chronyd

start stop 启停

对某服务进行启停操作:

systemctl start chronyd
systemctl stop  chronyd

status 查看当前状态

systemctl status chronyd

状态打印出来分为两大部分,上面为该 UNIT 的状态,下面为最近的日志。

状态栏里面有:

● chronyd.service - NTP client/server # 基本描述

Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; vendor preset: enabled) # 当前是否加载进内存(服务文件地址;;是否开机启动;)

Active: active (running) since 日 2022-11-27 17:25:18 CST; 1 day 4h ago # 当前运行情况;开始时间;持续时间

​ Docs: man:chronyd(8) # 在线文档地址 或者 man

​ man:chrony.conf(5)

Main PID: 6075 (chronyd) # 当前运行该 Unit 的进程

CGroup: /system.slice/chronyd.service # cgrpup 相关,包含调用栈

​ └─6075 /usr/sbin/chronyd

这里主要说下 Active:active(running),其实可能还有其他运行状态:

状态含义
active(running)表示程序正在执行
atcive(exited)执行一次就正常退出的服务,不在系统中执行任何程序
active(waiting)正在执行中,处于阻塞状态,需要等待其他程序执行完才能执行
inactive (dead)未启动状态

和开机启动项的状态(前面是当前状态,后面是默认状态):

启动状态含义
inactive服务关闭
disable服务开机不启动
enabled服务开机启动
static服务开机启动项被管理
failed服务配置错误

kill 杀死某服务

一般建议使用 stop 进行关闭,在无法 stop 情况下再使用该命令

systemctl kill chronyd

systemd 创建

我们刚刚看了很多关于 systemctl 的命令了,基本上学会了怎么进行使用,接下来我们需要自己创建一个 unit.server 进行一些简单的服务编排。

配置文件

在前面进行 status 命令讲解时,看到 Loaded 行有对应 server 的配置文件,我们以 chronyd 为例,查看这个程序是怎么加载的。

ll /usr/lib/systemd/system/chronyd.service
vim /usr/lib/systemd/system/chronyd.service

[Unit]

定义该 Unit 的加载问题和 status 上各种显示。

可选项描述
Description对当前服务的简单描述
After在XX启动后才启动。
Before在XX启动之前需要启动。
Conflicts异斥的服务,不能与这些服务共存。
Documentation使用手册说明,提供一个URIS的位置,一般用于man或者web访问,会被 status 公开,以便于发现。
ConditionPathExists这些路径存在才执行(如配置文件)。
Requires可以指定服务依赖于哪些服务(这种依赖是"强依赖",一旦所依赖的服务异常,当前的服务也随之停止)
Wants可以指定服务依赖于哪些服务(这种依赖是"弱依赖",即使所依赖的服务的启动情况不影响当前的服务是否启动)

[Install]

一般 [Install] 是在配置文件的最后一部分,是可选项。用于定义该 UNIT 的行为,一般是 enable 或者 disable 时发生调用。

[Install]描述
Alias别名,可使用systemctl command Alias.service
RequiredBy被哪些units所依赖,强依赖
WantedBy被哪些units所依赖,弱依赖
Also安装本服务的时候还要安装别的相关服务

[Service]

用于提供适用于 .service 的配置(只有 service,才需要这块)。

[Service]描述
EnvironmentFile环境配置文件,用来指定当前服务启动的环境变量
ExecStart指定服务启动时执行的命令或脚本
ExecStartPre指定服务启动前执行的命令或脚本
ExecStartPost指定服务启动后执行的命令或脚本
ExecStop指明停止服务要运行的命令或脚本
ExecStopPost指定服务停止之后执行的命令或脚本
RestartSec指定服务在重启时等待的时间,单位为秒
ExecReload指明重启服务要运行的命令或脚本
Restart当设定Restart=1 时,则当次daemon服务意外终止后,会再次自动启动此服务,具体看下列类型
PrivateTmp设定为yes时,会在生成/tmp/systemd-private-UUID-NAME.service-XXXXX/tmp/目录
KillModecontrol-goup 杀掉所有进程以及子进程;process 杀死主进程; mixed 给主进程发送 sigterm,字进程sigkill;none五操作
Restartno 退出后不重启;no-success 退出编码0重启;on-failure 退出不为0重启; on-abnormal 被kill或者超时时重启;on-abort 没有捕捉到信号时重启;on-watchdog 看门狗超时时重启;always 总是重启。
Typesimple ExecStart为主进程;forking 以fork()子进程执行; oneshot执行一次;notify 启动完毕后通知systemd; idle 其他任务结束才运行

其他种类 Unit [xxx] 部分

所以本篇文章不再意义列举了,可以参考:https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files

打印当前时间的服务

到这里我们已经可以开发很多种服务,挂载 systemd 上面了,那么我们就来个简单的每过 5s 打印一次当前时间的服务。

打印当前时间程序开发

在 /usr/bin/ 中新建文件 printNow.sh 进行打印:

vim /usr/bin/printNow.sh

#! /bin/bash
# Copyright◎2022, Maggot. All rights reserved.
#
# This program is print the now to screen.
# Date: 2022-11-28
# Auth: huangyichun
# Version: 0.1
date

# exit
# 更改权限
chmod 755 /usr/bin/printNow.sh

执行一次进行测试:

/usr/bin/printNow.sh

服务配置

进入到配置目录 /lib/systemd/system 中,编辑 myprint.service 文件:

cd /lib/systemd/system
vim myprint.service


[Unit]
Description=my print now
ConditionPathExists=/usr/bin/printNow.sh

[Service]
RestartSec=5s #每五秒进行一次
Type=simple
Restart=always
ExecStart=/usr/bin/printNow.sh
ExecReload=/usr/bin/printNow.sh
LimitNOFILE=102400

[Install]
WantedBy=multi-user.target

刷新 systemctl 服务

systemctl daemon-reload

查看 myprint 服务状态:

systemctl status myprint

启动 myprint 服务:

systemctl start myprint
systemctl status myprint

可以看到确实每 5s 运行了一次,但日志呢?

我们在 [Service] 中再添加(警告,centos8 可以使用):

vim /lib/systemd/system/myprint.service

# [Service] 中添加
StandardOutput=append:/tmp/myprintNow.log
StandardError=append:/tmp/myprintNow.log


systemctl daemon-reload
watch systemctl status myprint

这里看不到的原因是因为 restart 会清空日志。

以上是关于Linux systemctl 详解&自定义 systemd unit的主要内容,如果未能解决你的问题,请参考以下文章

linux命令之systemctl 详解

linux命令之systemctl 详解

linux命令之systemctl 详解

13个systemd与systemctl命令详解(linux)

systemctl 命令详解及使用教程

systemctl 命令详解及使用教程