Linux init、service、systemctl 三者区别

在接触到Linux 的服务之后,我所知道的管理服务的方式有三种,分别是initservicesystemctl

init

历史上,Linux 的启动一直采用init 进程。

在类Unix 的计算机操作系统中,Init(初始化的简称)是在启动计算机系统期间启动的第一个进程。

Init 是一个守护进程,它将持续运行,直到系统关闭。它是所有其他进程的直接或间接的父进程。

init 的参数全在/etc/init.d目录下,init.d 目录中存放的是一系列系统服务的管理(启动与停止)脚本。/etc/init.d 是指向 /etc/rc.d/init.d 的软连接。

init.d 初始化脚本称之为System V风格初始化,是System V系统传统之一,后来成为一些Unix系统的共同特性的源头。值得一提的是,在 /etc 目录下可能还包含 rc#.d 目录,这也是System V风格,#为数字0到6,为系统的运行级别runlevel。可见System V风格影响深远。

service 命令 可执行 init.d 目录中相应服务的脚本。service 是控制系统服务的实用工具。

1
$ sudo /etc/init.d/nginx start

service

通过查看man 手册页可以得知,service是一个运行System V init的脚本命令。

那么什么是 System V init 呢?

也就是/etc/init.d 目录下的参数。

所以分析可知service 是去/etc/init.d目录下执行相关程序,服务配置文件的存放目录就是/etc/init.d.

使用 service 启动一个服务

1
$ service nginx start

可以理解成 service 就是init.d 的一种实现方式。
所以这两者启动方式(或者是停止、重启)并没有什么区别。

1
2
3
$ sudo /etc/init.d/nginx start
// 等价于
$ service nginx start

但是这两种方式均有如下缺点:

  1. 启动时间长。init 进程是串行启动,只有前一个进程启动完,才会启动下一个进程。
  2. 启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。

systemd

Systemd 就是为了解决这些问题而诞生的。它包括 System and Service Manager,为系统的启动和管理提供一套完整的解决方案。
Systemd 是Linux 系统中最新的初始化系统(init),它主要的设计目的是克服 System V init 固有的缺点,提高系统的启动速度。

根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。

使用了 Systemd,就不需要再用init 了。Systemd 取代了initd(Initd 的PID 是0) ,成为系统的第一个进程(Systemd 的PID 等于 1),其他进程都是它的子进程。

Systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。

查看Systemd 的版本信息

1
$ systemctl --version

systemd-Linux系统基础组件集合

相关链接: systemd维基ArchLinux-systemdsystemctl 命令完全指南Systemd 入门教程 - 阮一峰

Systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。

systemd设计

https://zh.wikipedia.org/wiki/Systemd#%E8%AE%BE%E8%AE%A1

systemd.service(单元文件)

systemd.service 中文手册:https://www.jinbuguo.com/systemd/systemd.service.html

在一般的使用场景下,每一个 Unit(即服务) 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit 。

所有可用的 unit 文件位置,优先级从高到低

  • /etc/systemd/system/ :Local configuration。大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/systemctl enable 命令用于在两个目录之间建立符号链接关系;systemctl disable 命令用于在两个目录之间撤销符号链接关系;例如:

    1
    2
    $ systemctl enable rabbitmq
    Created symlink /etc/systemd/system/multi-user.target.wants/rabbitmq.service → /usr/lib/systemd/system/rabbitmq.service.
  • /run/systemd/system/ :Runtime units。一般是进程在运行时动态创建unit文件的目录,一般很少修改,除非是修改程序运行时的一些参数时,即Session级别的,才在这里做修改。

  • /usr/lib/systemd :Units of installed packages。等同于 /lib/systemd/,有系统(/usr/lib/systemd/system/)和用户(/usr/lib/systemd/user/)之分。供发行版打包者使用。

systemctl

监视和控制 systemd 的主要命令是 systemctl 。该命令可用于查看系统状态和管理系统及服务。详见systemctl(1)

1
2
3
4
5
6
7
8
9
10
11
# 查看所有可用的单元文件
[root@localhost ~]# systemctl list-unit-files | grep ''
# 查看所有已安装服务
[root@localhost ~]# systemctl list-unit-files --type=service | grep ''

# 输出激活的unit,下面两个命令等效
[root@localhost ~]# systemctl | grep ''
[root@localhost ~]# systemctl list-units | grep ''
# 输出激活的类型为service的unit
[root@localhost ~]# systemctl list-units --type=service | grep ''
[root@localhost ~]# systemctl list-units --type=service | grep nginx

编写单元文件

systemd - 编写单元文件

推荐链接:

1、编写有趣且有价值的 Systemd 服务

2、Systemd 服务:比启动停止服务更进一步

systemctl启动服务脚本编写使用

示例一

vim /etc/systemd/system/demo.service

注意:单元文件的注释必须独占一行,可以包含中文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# demo.service
[Unit]
Description= demo server
Documentation= https://zh.wikipedia.org/wiki/Systemd
After=syslog.target network.target network-online.target # 表示服务需要在***服务启动之后执行
Before= # 表示服务需要在***服务启动之前执行
Wants= # 弱依赖关系
Requires= # 强依赖关系,***服务停止之后本服务也必须停止

[Service]
EnvironmentFile=/etc/sysconfig/sshd # 环境参数文件
Type= simple # 默认simple:
# forking:
# notify:
User=<user>
Group=<group>
#UMask=0027
#NotifyAccess=all
#TimeoutStartSec=600
#LimitNOFILE=65536
WorkingDirectory=<WorkingDirectory>
Restart=on-failure # no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, always 之一,always 表示会被无条件的重启。 on-failure 表示 仅在服务进程异常退出时重启, 所谓"异常退出" 是指: 退出码不为"0"
RestartSec=10

SuccessExitStatus= # 额外定义其他的进程"正常退出"状态。 也就是,在退出码"0"、以及表示"正常退出"的 SIGHUP, SIGINT, SIGTERM, SIGPIPE 信号之外, 再额外添加一组表示"正常退出"的退出码或信号。 可以设为一系列 以空格分隔的数字退出码或者信号名称, 例如:SuccessExitStatus=1 2 8 SIGKILL,表示当进程的退出码是 1, 2, 8 或被 SIGKILL 信号终止时, 都可以视为"正常退出"。如果多次使用此选项, 那么最终的结果将是多个列表的合并。 如果将此选项设为空, 那么先前设置的列表 将被清空。
PrivateTmp=true # 开启安全Tmp系统功能。1、/tmp目录以及/var/tmp目录所有进程都在公用,不够安全,使用PrivateTmp后,进程用于自己的独立的目录以及相应的权限。2、关于目录的管理托管于systemd,即当systemd进程启动时会建立相应的目录(目录会在两个地方建立,/tmp以及/var/tmp/下建立两个目录),当通用systemd进程关闭时会删除相应的目录,不用程序单独处理。

ExecStartPre= # 启动服务之前执行的命令
ExecStart= # 启动进程时执行的命令
ExecStartPost= # 启动服务之后执行的命令

ExecReload= # 重启服务时执行的命令
ExecStop= /bin/sleep 10 # 停止服务时执行的命令,多个ExecStop按顺序执行。
ExecStop= /bin/sleep 20
ExecStop=
ExecStopPost= # 停止服务之后执行的命令

TimeoutStopSec= 180 # 1、设置每个 ExecStop= 的超时时长;2、设置该服务自身停止的超时时长

[Install]
WantedBy=multi-user.target

重新加载配置文件:systemctl daemon-reload

示例二

Nginx教程 章节的 开机自启动

使用单元

推荐链接: 使用unit