• Long Live Kubernetes!
  • 可关注微信公众第一时间知晓网站动态。 微信公众号
  • Long Live Linux!
  • 您觉得本站非常有看点,可以收藏本站,本站将持续推出高质量文章!
  • This site has been created and is maintained by and is the sole property of Yok8s.com. No part of this site may be copied or reproduced without express written consent from the authors of this site.

使用systemd管理服务生命周期

中间件 Rocloong 3个月前 (09-26) 70次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

Systemd 简介

Systemd是什么?以前linux系统启动机制是init,由于init对于进程的管理是串行化的,容易出现阻塞情况,另一方面init也仅仅是执行启动脚本,并不能对服务本身进行更多的管理。Systemd是为了更好解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案,根据Linux惯例,字母d是守护进程(daemon)的缩写,Systemd这个名字的含义,就是它要守护整个系统。使用了Systemd,就不需要再用init了。Systemd取代了initd,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。

Systemd作为进程管理工具优点

1、支持并行化任务;
2、同时采用socket式与D-Bus总线式激活服务;
3、按需启动守护进程(daemon);
4、利用Linux的cgroups监视进程;
5、支持快照和系统恢复;
6、维护挂载点和自动挂载点;
7、各服务间基于依赖关系进行精密控制。

Systemd管理系统资源

不同的系统资源统称为 Unit(单元),Unit一共分成以下12种,如下Unit类型:
1.Service:装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件
2.Target:多个Unit构成的一个逻辑组,用于对 Unit 文件进行逻辑分组,引导其它 Unit 的执行。它替代了 SysV-init 运行级别的作用,并提供更灵活的基于特定设备事件的启动方式
3.Device:硬件设备,主要用于定义设备之间的依赖关系
4.Mount:文件系统的挂载点,可以替代过去的 /etc/fstab 配置文件
5.Automount:自动挂载点,相当于 SysV-init 的 autofs 服务
6.Path:用于监控指定文件或路径的变化,并触发其它 Unit 运行
7.Scope:不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息
8.Slice:进程组,用于表示一个 CGroup 的树,通常也不是用户创建的
9.Snapshot:Systemd快照,可以切回某个快照
10. Socket:监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动
11. Swap:虚拟内存的交换分区
12. Timer Unit:定时器,用于配置在特定时间触发的任务,替代了 Crontab 的功能

Systemd Service配置文件

每一个被管理单元(Unit)都需要有一个配置文件用于告知systemd对于该单元(Unit)的管理方式。Systemd默认从目录/etc/systemd/system/读取配置文件,但是里面存放的大部分文件都是符号链接,指向目录/lib/systemd/system,配置文件存放于/lib/systemd/system/,开机启动后会在/etc/systemd/system目录建立软链接文件,systemctl enable命令用于在/etc/systemd/system/与/lib/systemd/system/两个目录之间建立符号链接关系。systemctl disable命令用于在两个目录之间撤销符号链接关系,相当于撤销开机启动。配置文件的后缀名,就是该Unit的种类,比如sshd.socket;如果命令行中省略后缀名,Systemd默认后缀名为.service,所以当systemctl enable sshd会被理解成systemctl enable sshd.service。

查看nginxsystemd配置文件

systemctl cat sshd.service

# /lib/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPost=/bin/sleep 0.1
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
LimitNOFILE=1000000
LimitNPROC=1000000
LimitCORE=1000000

[Install]
WantedBy=multi-user.target

通常一个service服务单元的配置包含3个区块:Unit,Service和Install

Unit区块

[Unit]区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。它的主要字段如下:

Description:简短描述
Documentation:文档地址
Requires:当前Unit依赖的其他Unit,如果它们没有运行,当前Unit会启动失败
Wants:与当前Unit配合的其他Unit,如果它们没有运行,当前Unit不会启动失败
BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前Unit停止运行
Before:如果该字段指定的Unit也要启动,那么必须在当前Unit之后启动
After:如果该字段指定的Unit也要启动,那么必须在当前Unit之前启动
Conflicts:这里指定的Unit 不能与当前Unit同时运行
Condition...:当前Unit运行必须满足的条件,否则不会运行
Assert...:当前Unit运行必须满足的条件,否则会报启动失败

Service区块

[Service]区块用来Service的配置,只有Service类型的Unit才有这个区块。它的主要字段如下:

Type:定义启动时的进程行为。它有以下几种值。
Type=simple:默认值,执行ExecStart指定的命令,启动主进程
Type=forking:以fork方式从父进程创建子进程,创建后父进程会立即退出
Type=oneshot:一次性进程,Systemd会等当前服务退出,再继续往下执行
Type=dbus:当前服务通过D-Bus启动
Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
Type=idle:若有其他任务执行完毕,当前服务才会运行
ExecStart:启动当前服务的命令
ExecStartPre:启动当前服务之前执行的命令
ExecStartPost:启动当前服务之后执行的命令
ExecReload:重启当前服务时执行的命令
ExecStop:停止当前服务时执行的命令
ExecStopPost:停止当其服务之后执行的命令
RestartSec:自动重启当前服务间隔的秒数
Restart:定义何种情况Systemd会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutSec:定义Systemd停止当前服务之前等待的秒数
Environment:指定环境变量
EnvironmentFile 指定加载一个包含服务所需的环境变量列表的文件,文件中的每一行都是一个环境变量的定义。

Install区块

[Install]通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下:

WantedBy:它的值是一个或多个Target,当前Unit激活时(enable)符号链接会放入/etc/systemd/system目录下面以Target名+.wants后缀构成的子目录中
RequiredBy:它的值是一个或多个Target,当前Unit激活时,符号链接会放入/etc/systemd/system目录下面以Target 名 + .required后缀构成的子目录中
Alias:当前Unit 可用于启动的别名
Also:当前Unit激活(enable)时,会被同时激活的其他Unit

占位符

在 Unit 文件中,有时会需要使用到一些与运行环境有关的信息,例如节点 ID、运行服务的用户等。这些信息可以使用占位符来表示,然后在实际运行中动态地替换为实际的值。

%n:完整的 Unit 文件名字,包括 .service 后缀名
%p:Unit 模板文件名中 @ 符号之前的部分,不包括 @ 符号
%i:Unit 模板文件名中 @ 符号之后的部分,不包括 @ 符号和 .service 后缀名
%t:存放系统运行文件的目录,通常是 “run”
%u:运行服务的用户,如果 Unit 文件中没有指定,则默认为 root
%U:运行服务的用户 ID
%h:运行服务的用户 Home 目录,即 %{HOME} 环境变量的值
%s:运行服务的用户默认 Shell 类型,即 %{SHELL} 环境变量的值
%m:实际运行节点的 Machine ID,对于运行位置每个的服务比较有用
%b:Boot ID,这是一个随机数,每个节点各不相同,并且每次节点重启时都会改变
%H:实际运行节点的主机名
%v:内核版本,即 “uname -r” 命令输出的内容
%%:在 Unit 模板文件中表示一个普通的百分号

服务监控启动

socket 触发的服务

涉及网络的服务,可以通过socket来触发启动。也就是说服务本身在没连接业务时不用一直空跑着,可以让systemd帮忙监听一个socket ,以减少资源消耗。当真正有业务连接进来时,才唤醒目标服务。要达成这样的配置,目标服务程序在实现上也有一定要求。

开发一个常规的网络服务,一般有以下几个关键步骤:

创建一个socket
调用bind将该 socket 绑定一个端口
调用listen监听端口,将该socket变成监听文件描叙符fd
调用accept接收一个客户端连接,得到一个新的连接文件描叙符fd
读写连接socket的fd,完成业务逻辑

借助systemd强大且通用的服务功能,它可以帮忙完成前两步,并且将socket的fd传给被激活的程序,后者就只要从第3步开始实现工作。
由socker触发的服务对应于systemd的配置文件要有两个,后缀分别是.socket与.service ,除后缀外的文件名要相同,这样就能自动关联。

例如名为nginx-socket的服务:
nginx-socket.socket

[Unit]Description=Hello World Socket [Socket]ListenStream=0.0.0.0:4321

nginx-socket.service

[Unit]Description=Hello World Socket Service 
[Service]ExecStart=/absolute/path/to/nginx-socket.exe

如上,.socket的配置,需要有[Socket]段,ListenStream字段表示了要监听的地址与端口。相应的 .service配置,与之前例子一样,描叙了如何启动服务。因为这是想由socket激活的service ,故没有配置重启字段。
在systemctl的大多数子命令中,如start ,其参数默认是假定 .service 单元 配置的。例如systemctl start nginx-socket等效于systemctl start nginx-socket.service 。但在这个例子中,有两种同名单元配置, 且按要求先只启动nginx-socket.socket ,所以要写完整的单元名:

systemctl start nginx-socket.socket

定时器触发的服务

对于定时器触发的服务首先要配置一个 .timer单元文件,例如:
nginx.timer

[Unit]Description=The nginx Timer [Timer]OnCalendar=*-*-* *:*:00

其中,OnCalendar 的配置格式同 crontab ,上例表示每分钟触发。
然后需要一个同名的 .service 单元文件。本文开头编译的 nginx.exe 正好 可作为该定时器启动的程序,例如:
nginx.service

[Unit]Description=The nginx Timer 
[Service]Type=oneshotExecStart=/absolute/path/to/nginx.exeStandardOutput=file:/absolute/path/to/stdout-file

然后启动定时器,并查看状态:

systemctl start nginx.timersystemctl status nginx.timer

服务异常重运行

为了确保服务在遭遇故障时能够自动重启。在Systemd的服务单元文件中,Restart指令是控制服务重启行为的核心设置。本文章将探讨Restart=on-failure与Restart=always这两个选项的区别,帮助开发人员对系统服务做出更适合的选择。Restart指令定义了当服务停止时Systemd的行为。它可以精细控制服务在遇到不同退出情况时是否应该重启。这是确保关键服务可靠性的重要机制,尤其是在生产环境中,服务的持续运行对业务至关重要。

智能重启

当服务单元文件中设置了Restart=on-failure时,Systemd会在服务因错误退出时尝试重启服务。”错误退出”通常是指服务以非零状态码结束运行,这可能是由于程序崩溃、遇到未处理的异常或其他非正常情况导致的。例如,如果你的服务由于内存不足而崩溃,on-failure将确保服务尝试重新启动。但如果服务是由于正常的系统维护任务而被停止,或者开发人员故意停止服务进行调试,那么它将不会被重启。

其应用场景如下:

生产环境:在不希望因为维护或更新操作而自动重启服务的生产环境中使用。

故障排除:当服务可能需要在出现问题时停止,以便进行故障排除时。

有条件的重启:当你只想在服务因特定问题而停止时重启。

无条件重启

与on-failure相对的是Restart=always选项。不管服务是如何终止的,系统都会尝试将其重启。这意味着即使服务被管理员有意关闭,或者服务正常结束,Systemd也会立即尝试将其重启。

这种策略适用于那些必须始终运行的服务,无论它们是因为何种原因停止的。这确保了即使在进行系统更新或维护时,服务也能尽可能快地恢复运行。

其应用场景如下:

关键服务:对于那些系统的核心功能,如数据库服务或Web服务器,这些服务的任何停机时间都是不可接受的。

高可用性要求:在需要最大程度减少服务停机时间的环境中。

简化管理:在希望无论服务如何停止都能立即重启的情况下。

实战演练

java应用使用systemd管理

查看配置文件:systemctl cat java.service

[Unit]
Description=springboot webapp
After=springboot-webapp.service

[Service]
WorkingDirectory=/home/app/springboot-webapp
Type=forking
Environment="JAVA_HOME=/home/app/jdk1.8.0_202"
Environment="PATH=/home/app/jdk1.8.0_202/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/.local/bin:/home/bin"
Environment="CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"
User=java
Group=java
PIDFile=/home/app/springboot-webapp/upp.pid
ExecStart=/home/app/springboot-webapp/start.sh
ExecStop=/home/app/springboot-webapp/stop.sh
PrivateTmp=true

[Install]
WantedBy=multi-user.target

java服务生命周期管理命令

启动服务:systemctl start java.service
关闭服务:systemctl stop java.service
重启服务:systemctl restart java.service
显示服务的状态:systemctl status java.service
在开机时启用服务:systemctl enable java.service
在开机时禁用服务:systemctl disable java.service
查看服务是否开机启动:systemctl is-enabled java.service
查看已启动的服务列表:systemctl list-unit-files|grep enabled
查看启动失败的服务列表:systemctl --failed

命令

systemctl是Systemd 的主命令,用于管理系统。

# 重启系统
$ sudo systemctl reboot
# 关闭系统,切断电源
$ sudo systemctl poweroff
# CPU停止工作
$ sudo systemctl halt
# 暂停系统
$ sudo systemctl suspend
# 让系统进入冬眠状态
$ sudo systemctl hibernate
# 让系统进入交互式休眠状态
$ sudo systemctl hybrid-sleep
# 启动进入救援状态(单用户状态)
$ sudo systemctl rescue

systemd-analyze命令用于查看启动耗时。

# 查看启动耗时
$ systemd-analyze 
# 查看每个服务的启动耗时
$ systemd-analyze blame
# 显示瀑布状的启动过程流
$ systemd-analyze critical-chain
# 显示指定服务的启动流
$ systemd-analyze critical-chain atd.service

查看配置文件

# 列出所有配置文件
# 这个列表显示每个配置文件的状态,一共有四种。
# enabled:已建立启动链接
# disabled:没建立启动链接
# static:该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖
# masked:该配置文件被禁止建立启动链接
$ systemctl list-unit-files
# 列出指定类型的配置文件
$ systemctl list-unit-files --type=service
# 查看当前系统的所有 Target
$ systemctl list-unit-files --type=target

查看系统Unit

# 列出正在运行的 Unit
$ systemctl list-units
# 列出所有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 cat docker.service

查看 Unit 的状态

# 显示系统状态
$ systemctl status
# 显示单个 Unit 的状态
$ systemctl status bluetooth.service
# 显示远程主机的某个 Unit 的状态
$ systemctl -H root@levonfly.example.com status httpd.service
# 显示某个 Unit 是否正在运行
$ systemctl is-active application.service
# 显示某个 Unit 是否处于启动失败状态
$ systemctl is-failed application.service
# 显示某个 Unit 服务是否建立了启动链接
$ systemctl is-enabled application.service

其它

systemd-analyze 显示此次系统启动时运行每个服务所消耗的时间,可以用于分析系统启动过程中的性能瓶颈
systemd-ask-password:辅助性工具,用星号屏蔽用户的任意输入,然后返回实际输入的内容
systemd-cat:用于将其他命令的输出重定向到系统日志
systemd-cgls:递归地显示指定 CGroup 的继承链
systemd-cgtop:显示系统当前最耗资源的 CGroup 单元
systemd-escape:辅助性工具,用于去除指定字符串中不能作为 Unit 文件名的字符
systemd-hwdb:Systemd 的内部工具,用于更新硬件数据库
systemd-delta:对比当前系统配置与默认系统配置的差异
systemd-detect-virt:显示主机的虚拟化类型
systemd-inhibit:用于强制延迟或禁止系统的关闭、睡眠和待机事件
systemd-machine-id-setup:Systemd 的内部工具,用于给 Systemd 容器生成 ID
systemd-notify:Systemd 的内部工具,用于通知服务的状态变化
systemd-nspawn:用于创建 Systemd 容器
systemd-path:Systemd 的内部工具,用于显示系统上下文中的各种路径配置
systemd-run:用于将任意指定的命令包装成一个临时的后台服务运行
systemd-stdio- bridge:Systemd 的内部 工具,用于将程序的标准输入输出重定向到系统总线
systemd-tmpfiles:Systemd 的内部工具,用于创建和管理临时文件目录
systemd-tty-ask-password-agent:用于响应后台服务进程发出的输入密码请求

《使用systemd管理服务生命周期》版权归作者所有,如需转载请注明出处,并附带文章链接地址,侵权必究!!!
喜欢 (1)
[]
分享 (0)
Rocloong
关于作者:
善战者无赫赫战功!
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到