👌 2020-02-17 Linux 系统 systemd 服务简介及编写
FileInfo Filename - Linux 编写系统 systemd 服务.md Version - v1.1.2002(2020/02/18 ~ 2020/02/19) Author - standuke Email - shadowdoker@gmail.com DescriptionKey - Linux Systemd Configure Set
本文约定
在文中将有以下提示符对重点进行标注说明,请注意文中提示。
⚠️ - 文中出现此标记,代表重要提示,指需要格外注意的地方 🔘 - 文中出现此标记,代表可选配置,建议配置,但不必要 ✅ - 文中出现此标记,代表检查项目,需要检查对应的配置文件 ❗️ - 文中出现此标记,代表该操作不可随意修改,如更改此步操作,请预先测试
[TOC]
systemd 概述
Red Hat Enterprise Linux 7(RHEL7)已经将服务管理工具从 SysVinit 和 Upstart(ubuntu) 迁移到了 systemd 上。
之前版本的所有启动脚本都是放在 /etc/rc.d/init.d/
目录下。这些脚本都是 bash 脚本,可以让系统管理员控制这些服务的状态。通常,这些脚本中包含了 start \ stop \ restart 这些方法,以提供系统自动调用这些方法。但是在 RHEL7 中已经完全摒弃了这种方法,而采用了一种叫 systemd 的 unit 的配置文件来管理服务。
unit 文件可用来描述:系统服务(.service)、挂载点(.mount)、sockets(.sockets)、系统设备(.device)、交换分区(.swap)、文件路径(.path)、启动目标(.target)、由 systemd 管理的计时器(.timer)
systemd 命令集
- systemctl 是 Systemd 的主命令,用于管理系统。
- systemd-analyze 用于查看启动耗时。
- hostnamectl 用于查看当前主机的信息。
- localectl 用于查看本地化设置。
- timedatectl 用于查看当前时区设置。
- loginctl 用于查看当前登录的用户。
RHEL7 服务启动相关文件
init
在 RHEL7 种与启动相关的 SysVinit(init) 文件以及文件夹如下所示,大部分使用的文件都是软链接
ll /etc/
lrwxrwxrwx. 1 root root 11 1月 16 08:59 init.d -> rc.d/init.d
// inittab 已弃用
-rw-r--r--. 1 root root 511 8月 9 2019 inittab
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc0.d -> rc.d/rc0.d
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc1.d -> rc.d/rc1.d
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc2.d -> rc.d/rc2.d
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc3.d -> rc.d/rc3.d
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc4.d -> rc.d/rc4.d
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc5.d -> rc.d/rc5.d
lrwxrwxrwx. 1 root root 10 1月 16 08:59 rc6.d -> rc.d/rc6.d
drwxr-xr-x. 10 root root 127 1月 16 08:59 rc.d
lrwxrwxrwx. 1 root root 13 1月 16 08:59 rc.local -> rc.d/rc.local
ll /etc/rc.d/
drwxr-xr-x. 2 root root 70 1月 16 08:59 init.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc0.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc1.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc2.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc3.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc4.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc5.d
drwxr-xr-x. 2 root root 45 1月 16 08:59 rc6.d
-rw-r--r--. 1 root root 473 8月 8 2019 rc.local
systemd
在 RHEL7 种与启动相关的 systemd 文件以及文件夹如下所示
/etc/systemd/system/*
# 供系统管理员和用户使用 ⚠️ 自定义服务需要放置在该目录
/run/systemd/system/*
# 运行时配置文件
/usr/lib/systemd/system/*
# 安装程序时默认的 unit 文件存放位置(如 RPM 包安装)
编写一个 服务
- 编写 unit 文件 demo.service
[Unit]
Description=My-demo Service
[Service]
Type=oneshot
ExecStart=/bin/bash /root/test.sh
StandardOutput=syslog
StandardError=inherit
[Install]
WantedBy=multi-user.target
- 将上述的文件拷贝到
RHEL7
系统中/usr/lib/systemd/system/*
目录下
cp demo.service /usr/lib/systemd/system/demo.service
- 编写 unit 文件中 ExecStart=/bin/bash /root/test.sh 所定义的 test.sh 文件,将其放在定义的目录当中,此文件是服务的执行主体。
#!/bin/bash
date >> /tmp/date
- 将 demo.service 设置为开机自启
systemctl enable demo.service
关键词详解
[Unit]:记录unit文件的通用信息 [Service]:记录Service的信息 [Install]:安装信息
Unit
● Description:对本service的描述。 ● Before, After:定义启动顺序,Before=xxx.service,代表本服务在xxx.service启动之前启动。After=xxx.service,代表本服务在xxx之后启动。 ● Requires: 这个单元启动了,那么它"需要"的单元也会被启动; 它"需要"的单元被停止了,它自己也活不了。但是请注意,这个设定并不能控制某单元与它"需要"的单元的启动顺序(启动顺序是另外控制的),即 Systemd 不是先启动 Requires 再启动本单元,而是在本单元被激活时,并行启动两者。于是会产生争分夺秒的问题,如果 Requires 先启动成功,那么皆大欢喜; 如果 Requires 启动得慢,那本单元就会失败(Systemd 没有自动重试)。所以为了系统的健壮性,不建议使用这个标记,而建议使用 Wants 标记。可以使用多个 Requires。 ● RequiresOverridable:跟 Requires 很像。但是如果这条服务是由用户手动启动的,那么 RequiresOverridable 后面的服务即使启动不成功也不报错。跟 Requires 比增加了一定容错性,但是你要确定你的服务是有等待功能的。另外,如果不由用户手动启动而是随系统开机启动,那么依然会有 Requires 面临的问题。 ● Requisite:强势版本的 Requires。要是这里需要的服务启动不成功,那本单元文件不管能不能检测等不能等待都立刻就会失败。 ● Wants:推荐使用。本单元启动了,它"想要"的单元也会被启动。但是启动不成功,对本单元没有影响。 ● Conflicts:一个单元的启动会停止与它"冲突"的单元,反之亦然。
Service
● Type:service的种类,包含下列几种类型: —-simple 默认,这是最简单的服务类型。意思就是说启动的程序就是主体程序,这个程序要是退出那么一切都退出。 —–forking 标准 Unix Daemon 使用的启动方式。启动程序后会调用 fork() 函数,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程 —–oneshot种服务类型就是启动,完成,没进程了。 notify,idle类型比较少见,不介绍。 ● ExecStart:服务启动时执行的命令,通常此命令就是服务的主体。 ——如果你服务的类型不是 oneshot,那么它只可以接受一个命令,参数不限。 ——多个命令用分号隔开,多行用 \ 跨行。 ● ExecStartPre, ExecStartPost:ExecStart执行前后所调用的命令。 ● ExecStop:定义停止服务时所执行的命令,定义服务退出前所做的处理。如果没有指定,使用systemctl stop xxx命令时,服务将立即被终结而不做处理。 ● Restart:定义服务何种情况下重启(启动失败,启动超时,进程被终结)。可选选项:no, on-success, on-failure,on-watchdog, on-abort ● SuccessExitStatus:参考ExecStart中返回值,定义何种情况算是启动成功。 eg:SuccessExitStatus=1 2 8 SIGKILL
Install
● WantedBy:何种情况下,服务被启用。 eg:WantedBy=multi-user.target(多用户环境下启用) ● Alias:别名
自启脚本接入
init 方式接入
⚠️ 默认 rc.local
弃用,但是仍然可以通过赋予执行权限 chmod +x /etc/rc.d/rc.local
来启用 rc.local
文件,此种方法即为 init 方式设置开机启动。
linux 启动时,先加载内核,然后加载 inittab
文件,inittab
文件中有个条目 si::sysinit:/etc/rc.d/rc.sysinit
指定了下一个要加载的文件 rc.sysinit
,这个文件加载完之后,加载 /etc/rc.d/rc.RUNLEVEL.d
目录中的启动脚本,最后加载 /etc/rc.d/rc.local
文件。
inittab
和 rc.sysinit
文件就不说了,在 rc.RUNLEVEL.d
文件夹里,所存的都是软链接,链接到 /etc/rc.d/init.d
中的脚本文件,而 /etc/rc.d/init.d
文件夹和 /etc/init.d
文件夹是一样的,/etc/init.d
其实是软链接到 /etc/rc.d/init.d
文件夹中。
若脚本需要开机启动,则方法如下
- 把脚本注册为系统服务,把它放到
/etc/init.d
目录下,并且在脚本中,加一行# chkconfig: 345 85 35
,然后就可以用chkconfig
命令让其开机启动。因为在/etc/init.d
目录下,所以也可以用service
命令控制该脚本。 - 建议 在
/etc/rc.d/rc.local
文件中,直接把该脚本的路径写进去,在开机加载rc.local
文件时,自然会启动这个脚本。这个脚本就不能用chkconfig
和service
命令控制。
systemd 方式接入
- 创建服务 unit 描述文件
- 设置开启自启
systemctl enable ***.service
- 重启检验
systemctl status ***.service
老版本兼容性
RHEL7 默认已经不再使用 SysVinit 和 Upstart,但是仍然可以兼容 SysVinit 和 Upstart
老版本 | 新版本 | 描述 |
---|---|---|
service name start | systemctl start name.service | Starts a service |
service name stop | systemctl stop name.service | Stops a service |
service name restart | systemctl restartname.service | Restarts a service |
service name reload | systemctl reloadname.service | Reloads configuration |
service name status | systemctl status name.service | Checks if a service status |
chkconfig name on | systemctl enablename.service | Enables a service |
chkconfig name off | systemctl disablename.service | Disables a service |
- 默认的 RunLevel(在 /etc/inittab 文件设置)现在被默认的 Target 取代,位置是 /etc/systemd/system/default.target,通常符号链接到 graphical.target(图形界面)或者 multi-user.target(多用户命令行)。
- 启动脚本的位置,以前是 /etc/init.d 目录,符号链接到不同的 RunLevel 目录 (比如 /etc/rc3.d、/etc/rc5.d 等),现在则存放在 /lib/systemd/system 和 /etc/systemd/system 目录。
- 配置文件的位置,以前init进程的配置文件是 /etc/inittab,各种服务的配置文件存放在 /etc/sysconfig 目录。现在的配置文件主要存放在 /lib/systemd 目录,在 /etc/systemd 目录里面的修改可以覆盖原始设置。
相关参考
systemd - Arch Linux https://wiki.archlinux.org/index.php/Systemd_(简体中文)#systemd_基本工具 阮一峰的网络日志 http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html IBM 浅析 Linux 初始化 init 系统,第 3 部分 https://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html 编写systemd下服务脚本 https://blog.csdn.net/fu_wayne/article/details/38018825