Linux必知必会08:daemon服务管理
在我们使用计算机时,除了我们正在使用的应用程序外,实际上系统后台还运行着很多进程,这些进程提供系统、网络等一些基础功能,以支持普通应用程序的运行。例如数据库、防火墙、sshd、计划任务等。
我们将这类进程称之为服务(service)。又因为这些进程是运行在系统后台,所以也将它们称之为守护进程(daemon)。
下面我们就来学习如何对Linux系统中的service进行管理,例如启动一个service、关闭一个service、让一个service开机自启等。
早期Linux系统采用init.d的方式对service进行管理,但最近版本的Linux系统都已经支持systemd的方式管理service,ubuntu系统目前同时支持两种方式的服务管理,下面我们将对这两种方式分别进行介绍。
init.d
在早期Linux系统中,当操作系统启动后,开始运行的第一个程序是/sbin/init,该程序的作用是初始化系统环境。
由于init是第一个启动的进程,它的进程编号pid就是1,其它的所有进程都是从init进程衍生出来的。下图可以看到init进程是整个系统中的第一个进程:

init进程的任务就是根据配置将系统开机后需要启动的service运行起来。但是,不同的使用场景可能需要启动不同的service,例如作为服务器需要启动sshd、mysql等服务,但作为桌面就不需要。
为了能让系统适应多种不同的使用场景(不同场景启动特定的服务),Linux引入了“运行级别(runlevel)”的概念,系统启动时会根据设置的运行级别自动运行特定的service。
Linux预置了七种运行级别(0-6)。一般来说,0是关机,1是单用户模式(维护模式),6是重启,2-5是多用户模式(也就是正常模式)。
那么,一个运行级别都会启动哪些service呢?每个运行级别在/etc目录下面,都有一个对应的子目录rc[x].d,在该目录中指定要运行的service:

在每个rc[x].d目录中存放的其实都是符号链接文件,这些符号链接都指向init.d目录下的bash脚本:

也就是说,真正的启动脚本都统一放在init.d这个目录中。
如果需要手动关闭或重启某个service,直接执行/etc/init.d目录下对应的bash脚本即可。例如,下面命令对mysql服务进行管理:
/etc/init.d/mysql start # 启动mysql服务
/etc/init.d/mysql restart # 重启mysql服务
/etc/init.d/mysql stop # 关闭mysql服务
/etc/init.d/mysql status # 查看mysql服务状态
也可以通过service命令调用/etc/init.d目录下的脚本:

可以看到两种管理service的方式本质上是相同的,执行service命令其实就是调用/etc/init.d目录下对应的bash脚本。
systemd
较新版本的Linux系统都已弃用init进程管理系统服务的方式,改用systemd对系统服务进行管理。相比于传统的init进程,systemd具有如下优势:
- 并行处理所有服务,加速开机流程:
init进程是串行启动服务的,即使是不依赖的服务也要一个一个的等待。systemd可以让所有的服务同时启动,这可以加快操作系统的启动速度。 - 自动检查服务间依赖:假设有两个服务A和B,B服务依赖A服务。当我们启动B服务时,如果A服务还没有被启动,那么systemd会帮我们自动启动A服务。
- 避免冗长的Bash脚本:
init进程只是执行bash脚本,不管其他事情。bash脚本需要自己处理各种情况,这往往使得脚本变得很长。systemd配置文件的语法更加简洁。 - 向下兼容init服务脚本:
/etc/init.d目录下的脚本也能够通过systemd对系统服务进行管理,所以旧的服务管理方式仍然能够正常工作。
/lib/systemd/systemd进程
采用systemd管理系统服务后,/lib/systemd/systemd就成为系统中的第一个进程(PID为1),其他进程都是从它衍生出来的子进程。
虽然在前面我们看到PID为1的进程仍然是/sbin/init,但实际上在最新版本的Ubuntu系统中,/sbin/init只是指向/lib/systemd/systemd的符号链接文件:

systemctl命令及其配置文件
对于那些支持systemd的软件,在安装的时候,会自动在/usr/lib/systemd/system目录下添加一个配置文件。例如mysql、firewalld等软件都会在该目录下存有对应的配置文件:

对于在/usr/lib/systemd/system目录下存有配置文件的这类软件,我们可以通过systemctl命令对其进行管理。
systemctl将所管理的资源抽象为unit,根据功能进行区分,不同的unit又分为不同的类型。unit的类型包括系统服务service、数据交换socket、unit的集合target等等。在/usr/lib/systemd/system目录下,不同类型的unit所对应的文件具有不同的扩展名。
这里我们只重点关注service和target这两种类型,可以像下面这样理解这两种类型的unit:
- service unit:一般服务类型,最经常使用的unit都是这种类型。与老版本Linux中的服务类似。
- target:一个unit组。与老版本Linux中的runLevel类似。在
/usr/lib/systemd/system目录下,你还可以看到一些target与传统runlevel的对应关系:

systemctl命令格式如下:
systemctl [command] [unit]
2command 包括:
3start : 立刻启动后面接的unit。
4stop : 立刻关闭后面接的unit。
5restart : 立刻重启后面接的unit,相当于先stop再start。
6reload : 不关闭后面接的unit的情况下,重新加载配置文件,让设置生效。
7enable : 设置下次开机时,后面接的unit会被自动启动。
8disable : 设置下次开机时,后面接的unit不会被自动启动。
9status : 查看一个unit的状态。
下面例子展示如何使用systemctl命令对mysql服务进行管理:

这里额外要注意的是enable和disable这两个命令,它们的作用实际上是在/etc/systemd/system目录下创建/删除一个指向/usr/lib/systemd/system目录中实际配置文件的符号链接。下面将ssh服务设置为开机自启:

可以看到,在/etc/systemd/system目录中,刚开始并不包含sshd.service这个符号链接文件。当我们将ssh服务设置为开机自启后,sshd.service符号链接文件才会被创建,它指向的就是位于/usr/lib/systemd/system目录下真正的ssh服务配置文件。
当操作系统启动时,它会先查看/etc/systemd/system目录下都有哪些配置文件,并启动那些配置文件对应的服务。
在/etc/systemd/system目录下放置的都是符号链接文件,实际的systemd启动配置文件都是放在/usr/lib/systemd/system目录下。所以如果你想要修改某个服务的启动设置,应该去修改/usr/lib/systemd/system目录下的配置文件才行。
查看系统上所有的服务
有两种方式查看系统中所有的服务,一种是使用list-units查看系统中所有启动的unit,另一种是使用list-unit-files根据/usr/lib/systemd/system目录下的内容列出所有已经安装的unit。其命令格式如下:
systemctl [command] [--type=TYPE] [--all]
command: list-units 或 list-unit-files
--type=TYPE: unit类型,可以是service、target、socket等
--all: list-units默认只会列出目前已启动的unit,若加上--all才会列出没启动的unit
使用list-units命令的效果如下:
systemctl list-units --type=service --all

使用list-unit-files命令的效果如下:
systemctl list-unit-files --type=service

systemctl配置文件
下面是mysql.service文件的内容:

unit配置文件的内容可以分为三大块:
- [Unit]部分是对一个unit的描述,与执行服务的依赖性有关;
- [Service]部分描述的是这个unit对应的实际程序及各项参数;
- [install]部分说明此unit要加入到哪个target中。
浙公网安备 33010602011771号