Linux服务管理神器:SYSTEMD介绍

笔者在日常的开发和使用中,经常需要写大量的本地服务并且进行管理,例如定时执行,定时查错,异步排队以及数据库的备份归档工作。因此systemd作为一个服务管理神器就成了必备工具。今天就写一篇小工具文来介绍一下这东西的用法。

一、SYSTEMD基本工具

监控和控制systemd主要使用的指令是systemctl。主要是从来看系统状态、服务状态,以及管理系统和服务。
同时systemctl可以通过ssh连接远程控制其他主机,使用 systemctl -H <username>@<URL> 格式。

1、分析系统状态

显示系统状态: $ systemctl status
输出激活的单元列表: $systemctl 或者 $systemctl list-units
输出运行失败的单元: $ systemctl —failed

所有可用的单元都在 /etc/systemd/system/(优先度高) 和 /usr/lib/systemd/system/(优先度低)。
查看所有已安装的服务:$ systemctl list-unit-files

2、使用单元

一个单元配置文件可以描述如下内容之一:系统服务(.service)、挂载点(.mount)、sockets(.sockets) 、系统设备(.device)、交换分区(.swap)、文件路径(.path)、启动目标(.target)、由 systemd 管理的计时器(.timer)。

我们通常在用systemctl调用单元的时候一般要单元文件的全名。也就是带上述后缀的那些。
如果不带扩展名的话systemctl会默认成是.service文件,所以为了不发生意外一般还是推荐把名字打全了。
挂载点和设备会自动转化为对应的后缀单元,比如/home就等价于home.mount, /dev/sda等价于dev-sda.device

systemctl在enable、disable、mask子命令里面增加了--now选项,可以激活同时启动服务,激活同时停止服务等。

立刻激活单元:$ systemctl start <unit>
立刻停止单元:$ systemctl stop <unit>
重启单元:$ systemctl restart <unit>
重新加载配置:$ systemctl reload <unit>
输出单元运行的状态:$ systemctl status <unit>
检测单元是否为自动启动:$ systemctl is-enabled <unit>
设置为开机自动激活单元:$ systemctl enable <unit>
设置为开机自动激活单元并现在立刻启动:$ systemctl enable --now <unit>
取消开机自动激活单元:$ systemctl disable <unit>
禁用一个单元:$ systemctl mask <unit>
取消禁用一个单元:$ systemctl unmask <unit>
显示单元的手册页(前提是由unit提供):$ systemctl help <unit>
重新载入整个systemd的系统配置并扫描unit文件的变动:$ systemctl daemon-reload

3、电源管理

注意:需要安装了polkit以后才能用普通用户身份进行电源管理。

重启:$ systemctl reboot
退出系统并关闭电源:$ systemctl poweroff
待机:$ systemctl suspend
休眠:$ systemctl hibernate
混合休眠模式:$ systemctl hybrid-sleep

二、编写unit文件

systemd的unit书写语法来源于XDG桌面配置文件,最初则来自于ini文件。
通过指令 $ systemctl show --property=UnitPath可以按照优先级查看unit加载目录。
/usr/lib/systemd/system/:软件包安装的单元
/etc/systemd/system/ :系统管理员安装的单元

1、处理依赖关系

主要有三类以外关系处理配置:
Requires=B:启动必须依赖单元B
Wants=B:启动依赖单元B(可选)
After=B:本单元在B运行后再运行

注意的是Requires和Want并没有包含After属性,如果不声明After则默认同时启动。

2、服务类型

Type=simple :(默认值) systemd认为该服务将立即启动。服务进程不会 fork 。
Type=forking :systemd认为当该服务进程fork,且父进程退出后服务启动成功。使用此启动类型应同时指定 PIDFile=,以便 systemd 能够跟踪服务的主进程。
Type=oneshot :这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使 systemd 在服务进程退出之后仍然认为服务处于激活状态。
Type=notify :与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。
Type=dbus :若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。
Type=idle :systemd会等待所有任务处理完成后,才开始执行 idle 类型的单元。其他行为与 Type=simple 类似。

3、修改现有的unit

直接修改文件并加载:$ systemctl daemon-reload
如果需要替换unit文件,则重新启用单元:$ systemctl reenable <unit>
或者运行:$ systemctl edit --full unit

附加配置片段:$ systemctl edit <unit>
这个操作会在编辑器里面打开/etc/systemd/system/<unit>.d/override.conf

重置到软件包版本:$ systemctl revert <unit>

三、目标 Target

目标是一个类似于运行界别的概念。一些目标能继承其他目标的服务并且启动新的服务,systemd默认提供了一部分类似于sysvinit运行级别的target。

获取当前的target:$ systemctl list-units --type=target
创建自定义target:我们可以新建一个/etc/systemd/system/<target>.target。然后再创建目录/etc/systemd/system/<target>.want,并且在里面加入需要启动的服务器连接(指向/usr/lib/systemd/system/)

SysV Level Systemd 目标 注释
0 runlevel0.target, poweroff.target 中断系统(halt)
1, s, single runlevel1.target, rescue.target 单用户模式
2, 4 runlevel2.target, runlevel4.target, multi-user.target 用户自定义运行级别,通常识别为级别3。
3 runlevel3.target, multi-user.target 多用户,无图形界面。用户可以通过终端或网络登录。
5 runlevel5.target, graphical.target 多用户,图形界面。继承级别3的服务,并启动图形界面服务。
6 runlevel6.target, reboot.target 重启
emergency emergency.target 急救模式(Emergency shell)

切换当前运行目标:$ systemctl isolate <target>.target
这个指令仅仅改变当前运行的target,不会对启动有影响

更改开机默认启动target:
检查当前的启动target:$ systemctl get-default
用systemctl修改default.target来变更开机启动target:$ systemctl set-default multi-user.target

四、临时文件

/usr/lib/tmpfiles.d//etc/tmpfiles.d/ 中的文件描述了 systemd-tmpfiles 如何创建、清理、删除临时文件和目录,这些文件和目录通常存放在 /run/tmp 中。配置文件名称为 /etc/tmpfiles.d/<program>.conf。此处的配置能覆盖 /usr/lib/tmpfiles.d/ 目录中的同名配置。

临时文件一般和服务文件同时提供,来生成守护进程需要的文件和目录。也可以在开机的时候往特定的文件写入一些内容。

五、定时器

1、服务单元

定时器是一个以.timer为结尾的unit配置文件,包含了systemd控制和监督的信息。很多时候可以替代crontab并且有更强的功能。
每一个.timer文件在同一个目录都有一个对应的.service文件。.timer用来激活并控制.service文件。.service文件不需要有[Install],这部分由.timer单元管理。

2、管理

使用.timer的方法也和其他unit一样,enable或者start即可。
查看已有的定时器使用:$ systemctl list-timers
查看所有的定时器(包括非活动的):$ systemctl list-timers --all

3、示例

下面是两个timer单元的例子。

单调定时器:

/etc/systemd/system/example.timer
----------------------------------
[Unit]
Description=Run example weekly and on boot        ## 文件描述
[Timer]
OnBootSec=15min                                   ## 开机后多久启动
OnUnitActiveSec=1w                                ## 执行间隔t
[Install]
WantedBy=timers.target                            ## 目标service单元

实时定时器:
定义一个定时执行,且上次未执行就立刻执行的timer

/etc/systemd/system/foo.timer
-----------------------------------
[Unit]
Description=Run foo weekly

[Timer]
OnCalendar=weekly
Persistent=true     
 
[Install]
WantedBy=timers.target
4、替代crontab探讨

优势主要在于,每个任务都有自己的systemd服务。从而:

  • 任务可以独立于定时器,便于测试。
  • 任务可以运行在特殊情况下。
  • 任务可以使用cgroups的特性。
  • 任务可以依赖于其他systemd unit。
  • 任务记录在systemd日志里,便于调试排查。

同时也可以和crontab一样在unit失效的时候发送一个email。不过现在一般都用其他开源监控工具,更好用。

六、挂载

因为systemd也负责按 /etc/fstab 挂在目录,所以在系统重启或者重新加载系统管理器的时候,systemd-fstab-generator会把/etc/fstab里面的配置转化为systemd unit。这些设置具体来说由 x-systemd组件来配置。

七、日志

systemd提供了自己的日至系统。
读取日志:$ journalctl

默认情况下(当 Storage= 在文件 /etc/systemd/journald.conf 中被设置为 auto),日志记录将被写入 /var/log/journal/。该目录是 systemd 软件包的一部分。

1、优先级

日志系统内有日志的优先级区分,下面为对应介绍:

优先级 介绍
优先级0 Emergency(emerg)
优先级1 Alert(alert)
优先级2 Critical(crit)
优先级3 Error(err)
优先级4 Warning(warning)
优先级5 Notice(notice)
优先级6 Informational(info)
优先级7 Debug(debug)
2、功能

在日志系统中,各个日志都会用编码来指代一定的功能区域。下面为对应介绍:

编码 内容(缩写)
功能编码0 kernel-message(kern)
功能编码1 user-level-message(user)
功能编码2 mail-system(mail)
功能编码3 system-daemon(daemon)
功能编码4 authorization-messages(auth)
功能编码5 syslog(syslog)
功能编码6 line-printer-subsystem(lpr)
功能编码7 network-news-subsystem(news)
功能编码8 uucp-subsystem(uucp)
功能编码9 clock-daemon
功能编码10 authpriv(authpri)
功能编码11 ftp-daemon(ftp)
功能编码12 tp-subsyst
功能编码13 log-audit
功能编码14 log-alert
功能编码15 crontab(cron)
功能编码16-23 local0-7
3、过滤输出

Journalctl可以过滤字段输出,下面为常用操作。

显示本次启动后所有日志:$ journalctl -b 或者 $ journalctl -b -0
显示上次启动后的日志:$ journalctl -b -1
显示上上次启动后的日志:$ journalctl -b -2
只显示错误冲突和重要告警信息:$ journalctl -p err..alert 或者用编号表示 $ journalctl -p 3..1
显示某个时间开始的消息:$ journalctl --since="2019-01-01 00:00:00"
显示最新的消息:$ journalctl -f
显示特定程序的所有消息:$ journalctl /usr/lib/systemd/systemd
显示某进程的所有信息:$ journalctl _PID=12345
显示指定unit的所有信息:$ journalctl -u mydumper-archive.service
指定内核缓存消息:$ journalctl -k
显示auth.log当前量:$ journalctl -f -1 SYSLOG_FACILITY=10

4、日志大小限制

默认情况下,systemd日志的最大限制是所在FS容量的10%。但是我们可以通过修改来改变最大限制:

/etc/systemd/journald.conf
--------------------------------
SystemMaxUse=50M

同时也可以通过配置片段而非全局来进行设置:

/etc/systemd/journald.conf.d/00-journal-size.conf
-----------------------------------
[Journal]
SystemMaxUse=50M
5、配合syslog

systemd提供了socket:/run/systemd/journal/syslog,来兼容传统日志服务。如果要让传统的日志服务工作,则要用这个socket来替代/dev/log。如果是使用rsyslog,则不用更改。

设置开机启动syslog-ng:$ systemctl enable syslog-ng

6、清理日志

所有的日志都存放在/var/log/journal,这个目录下其实rm也可以用来清理,但是不推荐。
下面的方法比较推荐。
清理日志到小于100MB:$ journalctl --vacuum-size=100M
清理最早两周前的日志:$ journalctl --vacuum-time=2weeks

八、疑难和差错

1、寻找错误

这个案例中我们以mydumper-ro.service为例
通过systemd寻找失败的服务:$ systemctl --state=failed
或者用systemd消息:$ journalctl -fp err
找到了错误unit后查看更多信息:$ systemctl status mydumper-ro
查到这个unit的PID是12345之后:$ journalctl -b _PID=12345
发现部分内核模块的配置文件有问题:$ ls -Al /etc/mydumper-ro.d
修复错误,最后重新启动服务即可。

2、诊断启动问题

在配置中使用内核参数引导:systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M

3、诊断一个服务

在服务的配置文件中加入诊断选项。

[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
4、短运行时间进程无日志

有时候某些短时间进程没有任何输出,没有日志。这个时候应该使用PID来查询。

5、禁止程序崩溃是转储内存

需要使用旧的内存转储则在对应的服务的配置文件中加入下面的设置:

/etc/sysctl.d/49-coredump.conf
-----------------------------------
kernel.core_pattern = core
kernel.core_uses_pid = 0
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,030评论 5 464
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,198评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,995评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,973评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,869评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,766评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,967评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,599评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,886评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,901评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,728评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,504评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,967评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,128评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,445评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,018评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,224评论 2 339