从 Linux 服务开机自启看 init 到 systemd 的演化

警告
本文最后更新于 2024-04-10,文中内容可能已过时。

从 Linux 服务开机自启看 init 到 systemd 的演化

如何设置开机自启

以 init 进程的方式

在 Centos7 上执行ll /etc/rc*

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost:~]$ ll /etc/rc*
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc0.d -> rc.d/rc0.d
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc1.d -> rc.d/rc1.d
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc2.d -> rc.d/rc2.d
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc3.d -> rc.d/rc3.d
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc4.d -> rc.d/rc4.d
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc5.d -> rc.d/rc5.d
lrwxrwxrwx.  1 root root  10 1月  18 15:15 /etc/rc6.d -> rc.d/rc6.d
lrwxrwxrwx.  1 root root  13 1月  18 15:16 /etc/rc.local -> rc.d/rc.local

/etc/rc.d:
总用量 4
drwxr-xr-x. 2 root root  70 1月  18 15:16 init.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc0.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc1.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc2.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc3.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc4.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc5.d
drwxr-xr-x. 2 root root  45 1月  18 15:16 rc6.d
-rw-r--r--. 1 root root 473 10月  2 2020 rc.local

可以看到/etc/rc0.d实际上是对/etc/rc.d/rc0.d的软连接,其他文件(/etc/rc1.d/etc/rc6.d/etc/rc.local)亦是如此。这些/etc/rc.d/rc0.d/etc/rc.d/rc6.d下分别存放是 linux 各个级别下执行启动或关闭的脚本,rcn.d (n 为 1 到 6) 是对应于不同的 runlevel 下起不同的服务。这些目录下都是一些符号连接,连接到init.d下的一些文件,以 S 开头的表示要启动,以 K 开头的不启动。第一个字母后面的数值是一个优先级,这个优先级是用 chkconfig 来维护的。

上面这段儿,出自101.3 Lesson 1SysVinit小节,说的很清楚:

The scripts used by init to setup each runlevel are stored in the directory /etc/init.d/. Every runlevel has an associated directory in /etc/, named /etc/rc0.d//etc/rc1.d//etc/rc2.d/, etc., with the scripts that should be executed when the corresponding runlevel starts. As the same script can be used by different runlevels, the files in those directories are just symbolic links to the actual scripts in /etc/init.d/. Furthermore, the first letter of the link filename in the runlevel’s directory indicates if the service should be started or terminated for the corresponding runlevel. A link’s filename starting with letter K determines that the service will be killed when entering the runlevel (kill). Starting with letter S, the service will be started when entering the runlevel (start). The directory /etc/rc1.d/, for example, will have many links to network scripts beginning with letter K, considering that the runlevel 1 is the single user runlevel, without network connectivity.

我们随便看看/etc/rc0.d下的内容

1
2
3
4
[root@localhost:/etc/rc.d/init.d]$ ll /etc/rc.d/rc0.d/
总用量 0
lrwxrwxrwx. 1 root root 20 1月  18 15:16 K50netconsole -> ../init.d/netconsole
lrwxrwxrwx. 1 root root 17 1月  18 15:16 K90network -> ../init.d/network

可以看到其内部的文件实际上就是对etc/rc.d/init.d下的文件的映射,我们看看/etc/rc.d/init.d这个目录下有什么

1
2
3
4
5
6
7
[root@localhost:/etc/rc.d/init.d]$ cd /etc/rc.d/init.d/
[root@localhost:/etc/rc.d/init.d]$ ll
总用量 40
-rw-r--r--. 1 root root 18281 5月  22 2020 functions
-rwxr-xr-x. 1 root root  4569 5月  22 2020 netconsole
-rwxr-xr-x. 1 root root  7928 5月  22 2020 network
-rw-r--r--. 1 root root  1160 10月  2 2020 README

有一个 README 文件,大概的意思如下,其中传统的 init 脚本已被本机 systemd 服务文件替换,服务文件提供了与 init 脚本非常相似的功能。要使用服务文件,只需调用“systemctl”,即使用“systemctl start|stop service_name”等实现启动关闭服务。而 functions 是一个脚本文件,系统启动时就会调用这个脚本,functions 文件包含了很多基础函数,设置参数等。

现在我们重点看/etc/rc.d/rc.local,我们把需要开机的时候执行的命令放到/etc/rc.d/rc.local中,系统启动的时候就会自动执行这些命令。

注意,需要为此文件赋权chmod +x /etc/rc.d/rc.local,确保系统系统时可以运行这个文件。

以 systemd 进程的方式

服务 (service) 管理 - 虾说全栈自定义 service 服务小节,我们已经学习过如何创建 Service 服务,创建完 Service 之后执行systemctl enable <service_name>设置服务开机自启。

这两种方式的对比

systemd 是目前 Linux 系统上主要的系统守护进程管理工具,由于 init 一方面对于进程的管理是串行化的,容易出现阻塞情况,另一方面 init 也仅仅是执行启动脚本,并不能对服务本身进行更多的管理。所以从 CentOS 7 开始也由 systemd 取代了 init 作为默认的系统进程管理工具。

正是因为 systemd 启动其他进程,所以它 pid 为 1,其他进程都是其子进程。

systemd 所管理的所有系统资源都称作 Unit,通过 systemd 命令集可以方便的对这些 Unit 进行管理。比如 systemctl、hostnamectl、timedatectl、localctl 等命令,这些命令虽然改写了 init 时代用户的命令使用习惯(不再使用 chkconfig、service 等命令),但确实也提供了很大的便捷性。

/etc/rc.d/rc.local这种开机自启的方式本质上依赖于 init 进程,而 init 进程从 Centos7 开始已经被 systemd 取代,因此从 Centos7 开始尽量使用 Service 的方式设置服务开机自启,而不是通过将命令放到/etc/rc.d/rc.local中的方式。

systemd 管理的优势

  1. 最新系统都采用 systemd 管理(RedHat7,CentOS7,Ubuntu15…)  

  2. CentOS7 支持开机并行启动服务,显著提高开机启动效率  

  3. CentOS7 关机只关闭正在运行的服务,而 CentOS6,全部都关闭一次。  

  4. CentOS7 服务的启动与停止不再使用脚本进行管理,也就是/etc/init.d下不再有脚本。  

  5. CentOS7 使用 systemd 解决原有模式缺陷,比如原有 service 不会关闭程序产生的子进程。

相关文件

systemd 控制的相关文件 CentOS6 CentOS7
服务启动的脚本启动路径 /etc/init.d /usr/lib/systemd/system
开机自启服务存放路径 /etc/rcN.d /etc/systemd/system/multi-user.target.wants/
默认运行级别配置文件 /etc/inittab /etc/systemd/system/default.target

从 init 到 systemd 进程的演化

Systemd 入门教程:命令篇 - 阮一峰的网络日志

Systemd 入门教程:实战篇 - 阮一峰的网络日志

看阮一峰大佬的博客得了。

0%