systemd添加与管理系统服务
上周的文章中,我们介绍了几种Linux上的文件共享策略,并提到了可以用systemctl将程序注册为系统服务。本篇将主要介绍一下注册为系统服务的具体方法。
systemd简介
Linux 操作系统的启动首先从 BIOS 开始,接下来进入 boot loader,由 bootloader 载入内核,进行内核初始化。内核初始化的最后一步就是启动 pid 为 1 的 init 进程。这个进程是系统的第一个进程,它以守护进程方式存在,是所有其他进程的祖先,负责产生其他所有用户进程。
早期的Linux 发行版的 init 系统是和 System V 相兼容的,被称为 System V init(也可简写为SysVinit),它依赖于Shell脚本进行启动项管理,因此具有概念简单清晰、易于维护等优点。然而随着Linux的发展以及Linux在移动设备上的广泛应用,SysVinit启动速度慢的缺点开始显现出来。人们开始改进这一启动系统,让它速度更快、支持的功能更多、更加自动化,并最终发展出了systemd(所有字母全小写)。
systemd的设计目标是,为系统的启动和管理提供一套完整的解决方案。根据 Linux 惯例,字母d
是守护进程(daemon)的缩写。 systemd 这个名字的含义,就是它要守护整个系统。它并不是一个单独的程序或命令,而是一组命令,涉及系统的方方面面。其中,systemctl
是 systemd 的主命令,用于管理系统。
下面是一些systemctl常用指令:
1 | # 重启系统 |
systemd的开机启动项
Linux系统在启动时要进行大量的初始化工作,比如挂载文件系统和交换分区、启动各类进程服务等,这些都可以看作是一个一个的单元(unit),并用一系列单元文件表示它们。systemd用目标(target)代替了System V init中运行级别的概念,这两者的区别如下表所示。
System V init运行级别 | systemd目标名称 | systemd 目标作用 |
---|---|---|
0 | poweroff.target | 关机 |
1 | rescue.target | 救援模式 |
2 | multi-user.target | 多用户的命令行界面 |
3 | multi-user.target | 多用户的命令行界面 |
4 | multi-user.target | 多用户的命令行界面 |
5 | graphical.target | 多用户的图形界面 |
6 | reboot.target | 重启 |
emergency | emergency.target | 救援模式 |
一般来说,我们最常接触到的运行级别只有multi-user.target
多用户命令行界面,其次是graphical.target
多用户图形界面(如果使用Linux桌面版的话)。因此,将服务进程的目标设定为multi-user.target
准没错。
单元文件的文件名以 .service
结尾,文件内容由 Unit、Service 和 Install 三个区块组成,分别用于描述启动顺序与依赖关系、定义启动行为、定义服务安装到的目标。以下是一个 service 脚本样例:
1 | [Unit] |
上述单元文件必须放在合适的目录中才能发挥作用。在Linux的systemd启动管理服务中,/lib/systemd/system/
和/etc/systemd/system/
这两个目录都用于存放系统服务的单元文件,但二者有所不同:
/lib/systemd/system/
目录是系统默认的服务单元文件,由系统或特定软件包来维护,不建议用户进行修改。/etc/systemd/system/
目录用于存放系统管理员创建或修改过的服务单元文件,在Linux启动过程中优先级更高。如果这个目录中存在与/lib/systemd/system/
中同名的单元文件,则后者的设置会被前者覆盖。
因此,我们可以通过在/etc/systemd/system/
目录中添加或修改单元文件,从而实现对开机启动项的修改。
一个例子
经过前面的介绍,我们已经知道可以通过在/etc/systemd/system/
中创建服务单元文件,从而实现开机自启动。这一小节中我们将展示一个实际例子(节选自 MCSManager的安装程序)。
首先,我们准备一份单元文件,内容如下所示:
1 | [Unit] |
上面这段代码定义了一个服务进程。我们将它保存为mcsm-daemon.service
文件,并存放在/etc/systemd/system/
目录下(需要root权限) 。这样以后,就可以使用 systemctl <command> mcsm-daemon.service
对这个进程进行操作了。
现在我们想让这个服务进程能够开机自启动。因此,我们运行下面的指令:
1 | systemctl enable mcsm-daemon.service --now # 参数`--now`要求立即启动这个服务进程。 |
其中, systemctl enable <service>
命令用于在系统启动时自动启动指定的服务。这个命令会创建一个符号链接,指向服务的单元文件。这样,当系统启动时,systemd会读取这些链接,并自动启动相应的服务。相应的,如果想要取消自启动,可以使用systemctl disable <service>
指令。
而如果要立即启动这个服务进程,则使用下面的指令:
1 | systemctl start mcsm-daemon.service |
其中, systemctl start <service>
命令用于立即启动指定的服务。这个命令不会创建任何符号链接,也不会改变系统的启动设置。它只是告诉systemd立即执行服务的启动操作。如果服务已经处于运行状态,start
命令通常不会有任何效果。相应的,如果想要取消自启动,可以使用systemctl stop <service>
指令。
要查看服务进程的运行状态,可以使用下面的指令:
1 | systemctl status mcsm-daemon.service |
其中, systemctl status <service>
命令用于查看服务进程的运行状态。上述指令的运行结果如下图所示:
以上。