文章目录
一、Systemd简介
Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置。Linux系统启动流程是由通电-BIOS-主引导记录-操作系统组成,开发者和程序员能够任性修改的天地基本都在操作系统各部分,其他部分已经被写死无法修改。操作系统的启动过程首先会加载内核文件,在读入成功后会启动init程序,它的作用是初始化系统环境。之后系统依据设定好的运行级别,即本次系统运行所扮演的角色,例如服务器、桌面模式、单用户模式、多用户模式、重启等等,运行级别一般是开机/默认指定好的,读取/etc目录下的配置文件可获得本次系统运行级别,/etc下配置文件还包含每一级运行级别所需要启动的进程名单,init初始化程序会以串行的脚本启动方法依次启动列表中的程序,至此系统初始化完成,用户可以对系统进行正常操作。
但事实上,init的系统初始化方法有两个重要的缺陷, 一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。
Systemd 就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。使用了 Systemd,就不需要再用init了。Systemd 取代了initd,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。
更多的介绍详见**这里**
综上所述,对于项目开发者,Systemd使得开发者可以安全的自定义项目系统启动的顺序,同时Systemd提供了完善的日志记录查找、服务状态查看维护等配套工具,大大方便了开发者对于系统自启动服务的掌控力。
二、设置步骤
1. 书写service文件
AlarmManagement.service(示例):
[Unit]
Description=AlarmManagement
Before=alarmstorage.service
After=gateway.service
[Service]
User=map
Type=forking
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/java/jdk-11.0.1/bin" ""
ExecStart=/usr/local/java/jdk/bin/java -jar /opt/map/module/alarmmanagement/AlarmManagement.jar
Restart=no
TimeoutSec=180
[Install]
WantedBy=multi-user.target
正如示例所展示,任一service文件均有Unit、Service、Install三部分组成,使用者需要依据systemd.unit文档中所提供的选项进行文件配置,下面只介绍一些常用选项
单元文件中的 [Unit] 小节 包含与单元类型无关的通用信息
Description= :有利于人类阅读的、对单元进行简单描述的字符串,将被 systemd 或其他程序用来标记此单元
Before= , After= :强制指定单元之间的启动先后顺序,接受一个空格分隔的单元列表
单元文件中的 [Service] 小节 含有所有单元启动过程中的配置功能选项
Type= :设置进程的启动类型。必须设为 simple(默认值), exec, forking, oneshot, dbus, notify, idle 之一
ExecStart= :启动该服务时需要执行的 命令行(命令+参数),除非 Type=oneshot ,否则必须且只能设置一个命令行
ExecStartPre=, ExecStartPost= :设置在执行 ExecStart= 之前/后执行的命令行。 语法规则与 ExecStart= 完全相同。
ExecStop= :这是一个可选的指令, 用于设置当该服务被要求停止时所执行的命令行。
TimeoutSec= :一个同时设置 超时时长 与 最大启动时长的快捷方式。
Restart= :当服务进程 正常退出、异常退出、被杀死、超时的时候,是否重新启动该服务。该选项的值可以取 no(默认值), on-success, on-failure, on-abnormal, on-watchdog, on-abort, always 之一
User=, Group= :设置进程在执行时使用的用户与组,默认是用户root
Environment= :设置进程的环境变量, 接受一个空格分隔的 VAR=VALUE 列表。
单元文件中[Install] 小节包含单元的启用信息。事实上,systemd 在运行时并不使用此小节。只有 systemctl的 enable 与 disable 命令在启用/停用单元时才会使用此小节。故在绝大部分情况下该部分无需自定义设置
关于各个选项的详细解释请看这里:Unit 、Service、Exce
2. Systemd自启动部署流程
1. 将写好的XXX.service文件放入systemd所指定的位置
Systemd启动时会加载一系列的单元目录(总共有10个),这些单元目录依照加载顺序分为优先级。
单元目录 | 描述 |
---|---|
/etc/systemd/system.control | 通过 dbus API 创建的永久系统单元 |
/run/systemd/system.control | 通过 dbus API 创建的临时系统单元 |
/run/systemd/transient | 动态配置的临时单元(系统与全局用户共用) |
/run/systemd/generator.early | 生成的高优先级单元(系统与全局用户共用) |
/etc/systemd/system | 本地配置的系统单元 |
/run/systemd/system | 运行时配置的系统单元 |
/run/systemd/generator | 生成的中优先级系统单元 |
/usr/local/lib/systemd/system | 本地软件包安装的系统单元 |
/usr/lib/systemd/system | 发行版软件包安装的系统单元 |
/run/systemd/generator.late | 生成的低优先级系统单元 |
事实上,在大部分情况简单需求下,使用者只需要将service文件放入/usr/lib/systemd/system才是正确的
网上很多教程所说的是/etc/systemd/system,这个是不符合规范的做法!
2.使用Systemd命令配置service单元使其生效
顺序执行以下命令即可完成自启动设置
- sudo systemctl daemon-reload (重新加载配置)
- sudo systemctl enable XXXX.service (将该单元加入开机启动列表)
注:每次修改完.service文件之后需要重新执行systemctl daemon-reload
建议在配置完成之后进行手动service启动测试
- sudo systemctl start XXXX(启动某service单元)
- sudo systemctl status XXXX(查看某service单元的运行状态)
- sudo systemctl stop XXXX(停止某service单元)
总结
事实上,使用systemd进行服务自启动的步骤十分简单,往往难住很多使用者的是对于service文件内容的书写出现错误所造成的,这其中牵扯到诸多细节问题,除去对于各个选项不理解的这一最常见问题外,还包括文件访问权限问题、配置环境问题、service文件重名覆盖问题等等,但幸好使用者可以通过systemd运行日志进行错误排查,后面一篇我将借助我遇到的systemd错误给大家展示如何进行排查。