Linux入门攻坚——20、systemd、(sysvinit、upstart重温)

再一次讲到Linux系统启动流程:
    POST --> Boot Sequence --> Bootloader(grub)  --> kernel + initramfs(initrd)  --> rootfs  --> /sbin/init

对于init,即系统内核加载完毕后(加载kernel和切换根文件系统)运行的第一个用户空间进程,是管理用户空间的首进程,其他用户进程都是直接或间接由此进程创建的。init 进程以守护进程的方式存在,负责组织与运行系统的相关初始化工作,让系统进入定义好的运行模式。对于不同的CentOS版本,init也不同:
    CentOS 5:SysV init
    CentOS 6:Upstart
    CentOS 7:systemd

CentOS5和6的init虽然不同,但进程名都是init,CentOS7则改成了systemd

对于SysVinit,执行的流程是:
内核加载完毕后,执行第一个进程init,即/sbin/init PID 为1。
启动init程序后,init进程首先读取/etc/inittab文件,分析文件内容,获得以下的配置信息:
    ▲ 系统需要进入的运行级别(runlevel)
    ▲ 捕获组合键的定义
    ▲ 定义电源fail/restore脚本
    ▲ 启动getty和虚拟控制台
获取系统运行级别之后,根据运行级别顺序的执行以下位置的启动脚本,从而将系统初始化为预设的运行级别:
    ▲ /etc/rc.d/rc.sysinit 重要的系统初始化服务
    ▲ /etc/rc.d/rc/etc/rc.d/rcX.d ,X为运行级别
    ▲ /etc/rc.d/rc.local 用户个性化服务
这样,整个系统就启动起来了。

/etc/rc.d/rc.sysinit执行一些重要的系统初始化任务:

  • 激活 udev 和 selinux
  • 设置定义在/etc/sysctl.conf 中的内核参数
  • 设置系统时钟
  • 加载 keymaps
  • 使能交换分区
  • 设置主机名(hostname)
  • 根分区检查和 remount
  • 激活 RAID 和 LVM 设备
  • 开启磁盘配额
  • 检查并挂载所有文件系统
  • 清除过期的 locks 和 PID 文件

/etc/rc.d/rc脚本文件,就是确定当前运行级别,然后遍历/etc/rc.d/rcX.d/目录下的文件(X是运行级别,如3级别,就是rc3.d),这些文件名字是有规律的,都是以K或S开头,后跟两位数字,在后面是脚本名字,并且,这些文件都是软链接,链接到/etc/init.d/下对应的脚本文件。如下:

 K##*,##运行次序,越小越先运行,K是Kill要关闭的,数字越小的服务,通常为依赖到别的服务。
 S##*,S是Start,要启动的,数字越小越先运行,数字小的服务,通常为被依赖到的服务。

为什么要使用软链接?因为rc0.d到rc6.d中都可能要运行这些脚本,每个目录下有一份拷贝,维护和存储都有问题,使用软链接,统一且空间占用少。

SysVinit是串行启动,即前一个脚本运行完,才能运行后面的,而不管之间是否存在依赖关系,速度慢,一个进程启动失败,容易导致其后所有进程无法启动,对于如文件系统挂载等不能很好的处理,如usb即插即用支持不好。

对于Upstart
针对SysVinit的缺点,Ubuntu 开发人员重新设计和开发一个全新的 init 系统,即 UpStart。UpStart 基于事件机制,比如 U 盘插入 USB 接口后,udev 得到内核通知,发现该设备,这就是一个新的事件。UpStart 在感知到该事件之后触发相应的等待任务,比如处理/etc/fstab 中存在的挂载点。采用这种事件驱动的模式,upstart 完美地解决了即插即用设备带来的新问题。

此外,采用事件驱动机制也带来了一些其它有益的变化,比如加快了系统启动时间。sysvinit 运行时是同步阻塞的。一个脚本运行的时候,后续脚本必须等待。这意味着所有的初始化步骤都是串行执行的,而实际上很多服务彼此并不相关,完全可以并行启动,从而减小系统的启动时间。

Upstart 的特点:UpStart 解决了之前提到的 sysvinit 的缺点。采用事件驱动模型,UpStart 可以:
    更快地启动系统
    当新硬件被发现时动态启动服务(PnP,英文 Plug-and-Play,译文为即插即用)
    硬件被拔除时动态停止服务

Upstart 概念和术语
UpStart 主要的概念是 job 和 event。
(一)Job
Job是一个工作的单元(unit),一个任务(task)或者一个服务(service)。每个 Job 都等待一个或多个事件,一旦事件发生,UpStart 就触发该 Job 完成相应的工作。可以理解为 sysvinit 中的一个服务脚本。有三种类型的工作:
    ● task job;
    ● service job;
    ● abstract job;
task job 代表在一定时间内会执行完毕的任务,比如删除一个文件;
service job 代表后台服务进程,比如 apache httpd。这里进程一般不会退出,一旦开始运行就成为一个后台精灵进程,由 init 进程管理,如果这类进程退出,由 init 进程重新启动,它们只能由 init 进程发送信号停止。它们的停止一般也是由于所依赖的停止事件而触发的,不过 upstart 也提供命令行工具,让管理人员手动停止某个服务;
Abstract job 仅由 upstart 内部使用。

init daemon会监测每个服务的状态,如果服务出现问题会重启服务,在某些事件触发时或手工停止时会杀死服务。
Upstart init daemon只能监测那些使用exec运行的作业,无法监测使用script…end script运行的作业。也就是说,服务应该使用exec运行,而任务则可以使用任意的方法。
Upstart init守护进程读取/etc/init目录下的作业配置文件,并使用inotify来监控它们的改变。配置文件名必须以.conf结尾,可以放在/etc/init/下的子目录中。每个文件定义一个服务或作业,其名称按路径名来称呼。例如定义在/etc/init/rc-sysinit.conf中的作业就称为rc-sysinit,而定义在/etc/init/net/apache.conf的作业称为net/apache。这些文件必须是纯文本且不可执行的。

进程(Process):  Process是由工作(jobs)定义的服务(Services)或者任务(Task),它将被init daemon运行。每个job可以定义一个或者多个不同的process,分别在其生命周期的不同状态运行。除抽象作业(Abstact Job)外的所有作业配置文件都必须要含有exec节(exec stanza)或者script节(script stanza)。它们指定这个工作运行什么文件。

除了以上的分类之外,还有另一种工作(Job)分类方法。Upstart 不仅可以用来为整个系统的初始化服务,也可以为每个用户会话(session)的初始化服务。系统的初始化任务就叫做 system job,比如挂载文件系统的任务就是一个 system job;用户会话的初始化服务就叫做 session job。

Job 生命周期
Upstart 为每个工作都维护一个生命周期。一般来说,工作有开始,运行和结束这几种状态。为了更精细地描述工作的变化,Upstart 还引入了一些其它的状态。比如开始就有开始之前(pre-start),即将开始(starting)和已经开始了(started)几种不同的状态,这样可以更加精确地描述工作的当前状态。

工作从某种初始状态开始,逐渐变化,或许要经历其它几种不同的状态,最终进入另外一种状态,形成一个状态机。在这个过程中,当工作的状态即将发生变化的时候,init 进程会发出相应的事件(event)。

Upstart 中 Job 的可能状态

状态名  :    含义
Waiting   : 初始状态
Starting  Job  : 即将开始
pre-start   : 执行 pre-start 段,即任务开始前应该完成的工作
Spawned : 准备执行 script 或者 exec 段
post-start  : 执行 post-start 动作
Running  : interim state set after post-start section processed denoting job is running (But it may have no associated PID!)
pre-stop : 执行 pre-stop 段
Stopping   : interim state set after pre-stop section processed
Killed : 任务即将被停止
post-stop : 执行 post-stop 段

有四个状态会引起 init 进程发送相应的事件,表明该工作的相应变化:
Starting、Started、Stopping、Stopped,而其它的状态变化不会发出事件。

事件 Event
Event 就是一个事件。事件在 upstart 中以通知消息的形式具体存在。一旦某个事件发生了,Upstart 就向整个系统发送一个事件消息,依赖于该事件的程序就会开始运行。没有任何手段阻止事件消息被 upstart 的其它部分知晓,也就是说,事件一旦发生,整个 upstart 系统中所有工作和其它的事件都会得到通知。
Event 可以分为三类: signal,methods 或者 hooks
常见事件:
系统上电启动,init 进程会发送"start"事件
根文件系统可写时,相应 job 会发送文件系统就绪的事件
一个块设备被发现并初始化完成,发送相应的事件
某个文件系统被挂载,发送相应的事件
类似 atd 和 cron,可以在某个时间点,或者周期的时间点发送事件
另外一个 job 开始或结束时,发送相应的事件
一个磁盘文件被修改时,可以发出相应的事件
一个网络设备被发现时,可以发出相应的事件
缺省路由被添加或删除时,可以发出相应的事件

Job 和 Event 的相互协作
Upstart 就是由事件触发工作运行的一个系统,每一个程序的运行都由其依赖的事件发生而触发的。

系统初始化的过程是在工作和事件的相互协作下完成的,可以大致描述如下:系统初始化时,init 进程开始运行,init 进程自身会发出不同的事件,这些最初的事件会触发一些工作运行。每个工作运行过程中会释放不同的事件,这些事件又将触发新的工作运行。如此反复,直到整个系统正常运行起来。

启动一个作业的流程

  1)Upstart把作业的目标从stop改成start。正如目标的名字指示的一样,作业(实例)现在尝试启动。目标可以用initctl list和status命令显示。
  2)Upstart触发starting事件,指示作业即将启动。这个事件包括两个环境变量:JOB指定作业名;INSTANCE指定实例名,如果启动单一的实例(没有instance配置节),则实例名为空。
  3)starting事件完成。
  4)如果pre-start节存在,则产生pre-start进程。如果pre-start失败,Upstart把目标从start改成stop,设置表示失败的变量并触发stopping和stopped事件。
  5)Upstart产生主进程。即运行script或exec配置节,如果没有script或exec配置节,则Upstart什么也不做。
  6)Upstart确定作业的最终PID,可参考expect fork和expect守护r进程。
  7)如果post-start配置节存在,则产生post-start进程。。如果post-start失败,Upstart把目标从start改成stop,设置表示失败的变量并触发stopping和stopped事件。
  8)Upstart触发started事件。这个事件包含与starting同样的环境变量。对Service job,当started事件完成后,主进程即完全地运行起来了。如果是Task job,则任务执行完成(成功或失败)。

  终止一个作业的流程

  1)Upstart把作业的目标从start改为stop。现在作业(实例)尝试终止。
  2)如果pre-stop配置节存在,则产生pre-stop进程。如果pre-stop失败,Upstart设置表示失败的变量,并触发stopping和stopped事件。
  3)如果作业有script或exec配置节,则终止主进程,首先向主进程发送SIGTERM信号,然后Upstart等待kill timeout秒数(默认为5秒),如果进程仍然在运行,则向进程发送SIGKILL信号,因为进程不能选择忽略此信号,因此能保证进程被终止。
  4)Upstart触发stopping事件。这个事件有一系列的相关环境变量,包括:
  JOB: 与本事件关联的作业名。
  INSTANCE: 实例名。
  RESULT: “ok”表示作业正常退出,”failed”表示作业失败,注意退出结果的显示可以用normal exit配置节修改。
  PROCESS: 导致作业失败的配置节名称。如果RESULT=ok,则本变量不会被设置。如果设置了,可能值有pre-start, post-start, main(表示script或exec配置节), pre-stop, post-stop, respawn(表示作业产生次数超过了respawn limit配置节设置的限制)。
  EXIT_STATUS或EXIT_SIGNAL: 如果作业自己退出则设置EXIT_STATUS,如果由于接收到信号退出则设置EXIT_SIGNAL。如果两个变量都没有设置,则进程在产生的过程中出现了问题(例如指定要运行的命令没有找到)。
  5)如果post-stop配置节存在,则生成post-stop进程。如果post-start失败,Upstart设置表示失败的变量并触发stopped事件。
  6)Upstart触发stopped事件。当stopped事件完成后,作业即完全终止。stopped事件与stopping事件有相同的环境变量集。

究竟哪些事件会触发某个工作的运行?这是由工作配置文件定义的。

1.工作配置文件
任何一个工作都是由一个工作配置文件(Job Configuration File)定义的。这个文件是一个文本文件,包含一个或者多个小节(stanza)。每个小节是一个完整的定义模块,定义了工作的一个方面,比如 author 小节定义了工作的作者。工作配置文件存放在/etc/init 下面,是以.conf 作为文件后缀的文件。

比较重要的小节有以下几个:
(1)“expect” Stanza
Upstart 除了负责系统的启动过程之外,和 SysVinit 一样,Upstart 还提供一系列的管理工具。当系统启动之后,管理员可能还需要进行维护和调整,比如启动或者停止某项系统服务。或者将系统切换到其它的工作状态,比如改变运行级别。

为了启动,停止,重启和查询某个系统服务。Upstart 需要跟踪该服务所对应的进程。比如 httpd 服务的进程 PID 为 1000。当用户需要查询 httpd 服务是否正常运行时,Upstart 就可以利用 ps 命令查询进程 1000,假如它还在正常运行,则表明服务正常。当用户需要停止 httpd 服务时,Upstart 就使用 kill 命令终止该进程。为此,Upstart 必须跟踪服务进程的进程号。

部分服务进程为了将自己变成后台守护进程(daemon),会采用两次派生(fork)的技术,另外一些服务则不会这样做。假如一个服务派生了两次,那么 UpStart 必须采用第二个派生出来的进程号作为服务的 PID。但是,UpStart 本身无法判断服务进程是否会派生两次,为此在定义该服务的工作配置文件中必须写明 expect 小节,告诉 UpStart 进程是否会派生两次。

Expect 有两种,"expect fork"表示进程只会 fork 一次;"expect daemonize"表示进程会 fork 两次。

(2)“exec” Stanza 和"script" Stanza
一个 UpStart 工作一定需要做些什么,可能是运行一条 shell 命令,或者运行一段脚本。用"exec"关键字配置工作需要运行的命令;用"script"关键字定义需要运行的脚本。

(3)“start on” Stanza 和"stop on" Stanza
"start on"定义了触发工作的所有事件。"start on"的语法很简单,如下所示:

start on EVENT [[KEY=]VALUE]… [and|or…]

EVENT 表示事件的名字,可以在 start on 中指定多个事件,表示该工作的开始需要依赖多个事件发生。多个事件之间可以用 and 或者 or 组合,"表示全部都必须发生"或者"其中之一发生即可"等不同的依赖条件。除了事件发生之外,工作的启动还可以依赖特定的条件,因此在 start on 的 EVENT 之后,可以用 KEY=VALUE 来表示额外的条件,一般是某个环境变量(KEY)和特定值(VALUE)进行比较。如果只有一个变量,或者变量的顺序已知,则 KEY 可以省略。

"stop on"和"start on"非常类似,只不过是定义工作在什么情况下需要停止。

systemd

systemd是目前最流行的init程序,通过套接字激活的机制,让所有无论有无依赖关系的程序全部并行启动,并且仅按照系统启动的需要启动相应的服务,最大化提高开机启动速度。Systemd使用单个配置文件来管理所有服务,并提供了丰富的命令行工具来管理服务。Systemd还支持动态加载和卸载服务,可以在系统运行时添加或删除服务。

systemd架构:

systemd体系架构如下:
最底层:​​systemd 内核层​​面依赖 cgroup、autofs、kdbus
第二层:​​systemd libraries​​ 是 systemd 依赖库
第三层:​​systemd Core​​ 是 systemd 自己的库
第四层:​​systemd daemons​​ 以及 targets 是自带的一些基本 unit、target,类似于 sysvinit 中自带的脚本
最上层:就是和 systemd 交互的一些工具,比如systemctl;

systemd 的守护进程主要分为系统态(system)与用户态(user)

PID为1的进程/sbin/init就是system态的systemd,是一个软链接,指向真实的 systemd 路径,一般放在/usr/lib/systemd/目录

systemd 为进程服务集合的总称,它包含许多的进程,负责控制、管理系统的资源,其中包括 systemd-login,负责用户登录相关信息的创建、修改与删除;systemd-sleep 控制系统的休眠、睡眠状态切换等等。主要集中在/usr/lib/systemd/文件目录:

systemd新特性
    ● 系统引导时实现服务并行启动:可以并行启动多个服务,提高系统的启动速度。启动速度的快慢取决于系统中启动的服务数量和服务启动顺序。在启动过程中,Systemd 会根据服务之间的依赖关系并行启动服务,从而尽量减少服务之间的等待时间,Systemd 还会对服务进行优先级排序,将优先级高的服务优先启动,加快系统启动的时间。其他一些优化措施,如,使用二进制日志格式来记录系统日志,支持动态加载和卸载服务,可以在系统运行时添加或删除服务,而无需重启系统,从而减少了系统的停机时间。
    ● 按需激活进程:只有在某个服务被真正请求的时候才启动它,这称为“启动时懒加载”(Lazy Loading);按需启动服务的功能需要服务单元支持。
    ● 系统状态快照;
    ● 基于依赖关系定义服务控制逻辑:systemd 维护一个"事务一致性"的概念,保证所有相关的服务都可以正常启动而不会出现互相依赖,以至于死锁的情况;每个服务单元都可以指定一组依赖项,这些依赖项可以是其他服务单元、套接字、挂载点等。Systemd 通过事务性依赖关系管理来确保依赖项按正确的顺序启动,并且在依赖项未满足时暂停或者终止服务单元。事务性依赖关系管理的核心思想是事务(transaction),即将所有依赖项按正确的顺序组合成一个事务,并且在该事务中启动、停止或重新启动服务单元。当一个服务单元的依赖项未满足时,Systemd 会暂停或终止该服务单元,并且等待依赖项满足后再重新启动。
事务性依赖关系管理的实现主要包括以下几个方面:
    依赖图分析:Systemd 使用依赖图来描述服务单元之间的依赖关系,并且通过分析依赖图来确定正确的启动顺序。
    事务管理器:Systemd 使用事务管理器来管理依赖项的启动、停止或重新启动,并且在依赖项未满足时暂停或终止服务单元。
    依赖项状态追踪:Systemd 会追踪每个依赖项的状态,并且在依赖项状态发生变化时重新计算依赖关系。

核心概念:unit(单元) 是 Systemd 中管理和控制系统资源、服务或任务的基本单元,每个 unit 都有独有的名称、类型和配置文件,并且通过依赖关系来控制 unit 的启动和停止顺序。
    配置文件进行标识和配置:文件中主要包含了系统服务、监听socket、保存的系统快照以及其他与init相关的信息;
    保存至:
        /usr/lib/systemd/system/:该目录包含了所有已安装软件的服务单元文件,包括系统服务和第三方软件服务。
        /run/systemd/system/:该目录包含了所有正在运行的服务单元文件,这些服务单元文件是基于 /etc/systemd/system/ 和 /usr/lib/systemd/system/ 目录中的文件生成的。
        /etc/systemd/system/:该目录包含了所有本地系统服务单元文件的配置文件,包括启动时运行的系统服务和用户服务。
        /etc/systemd/system.conf:该文件包含了 Systemd 的全局配置。
        /etc/systemd/user/:该目录包含了用户定义的服务单元文件,这些服务单元文件会在用户登录时自动启动。
        /etc/systemd/logind.conf:该文件包含了 login 管理器的配置,用于管理用户登录时的会话。
        /etc/systemd/systemd-journald.conf`:该文件包含了 journal 日志的配置,用于管理系统日志。
        /etc/systemd/timesyncd.conf:该文件包含了 timesyncd 时间同步服务的配置。
        /usr/lib/systemd/systemd-sleep:该目录包含了睡眠模式相关的服务脚本。

unit的类型:
    Service unit:文件扩展名为.service,用于定义系统服务;
    Target unit:文件扩展名为.target,用于模拟实现“运行级别”
    Device unit:扩展名为.device,用于定义内核识别的设备
    Mount unit:扩展名为.mount,定义文件系统挂载点
    Socket unit:扩展名为.socket,用于标识进程间通信用的socket文件
    Snapshot unit:扩展名为.snapshot,管理系统快照
    Swap unit:扩展名为.swap,用于标识swap设备
    Automount unit:扩展名为.automount,文件系统的自动挂载点;
    Path unit:扩展名为.path,用于定义文件系统中的一个文件或目录

Unit: 是 Systemd 的基本构建块,用于定义系统服务和其他资源,包括服务的启动顺序、依赖关系、部署状态等。每个 Unit 都有一个唯一的名字和类型,例如 service、socket、mount 等。
在 Unit 文件中,可以定义以下信息:
    1)Unit 的类型、名称和描述
    2)Unit 之间的依赖关系和启动顺序
    3)Unit 的执行程序、启动参数和环境变量
    4)Unit 的状态和执行结果
    5)Unit 的启动、停止、重启和状态查询等操作

Target: 是一组相关的 Unit 的集合,用于定义系统运行的目标状态。每个 Target 都有一个唯一的名字和一组依赖的 Unit,当系统启动时,Systemd 会尝试启动指定的 Target,从而满足系统运行的需求。在 Target 文件中,可以定义以下信息:
    1)Target 的名称和描述
    2)Target 所包含的 Unit 和依赖关系
    3)Target 的启动、停止、重启和状态查询等操作
Target 的类型和 Unit 的类型类似,例如 multi-user、graphical、network 等。其中,multi-user.target 用于启动多用户命令行界面,graphical.target 用于启动图形化界面,network.target 用于启动网络服务等。
    总之,Unit 和 Target 是 Systemd 的核心概念,通过定义 Unit 和 Target,可以对系统服务和状态进行管理和控制。

查看一个服务属于哪个target,只需要看[install]部分就可以看出属于哪个target

在 Systemd 中,Unit 的状态有以下几种:

  • active (running):Unit 正在运行。
  • active (exited):Unit 已经完成运行并退出。
  • inactive (dead):Unit 已经停止运行。
  • activating (start):Unit 正在启动。
  • activating (auto-restart):Unit 正在自动重启。
  • deactivating (stop):Unit 正在停止。
  • deactivating (restart):Unit 正在重启。
  • failed:Unit 启动失败,或者在运行过程中突然停止。

关键特性:
    基于socket的激活机制:socket与服务程序分离,
    基于bus的激活机制:
    基于device的激活机制:
    基于path的激活机制:
    系统快照:保存各unit的当前状态信息于持久存储设备中;
    向后兼容sysv init脚本;

不兼容特性:
    systemctl命令固定不变
    非由systemd启动的服务,systemctl无法与之通信

管理系统服务:
    CentOS 7:通过service unit来管理服务
    注意:能兼容早期的服务脚本

    命令:systemctl COMMAND name.service

服务6与7的差别:
启动:service name start ==> systemctl start name.service
停止:service name stop ==> systemctl stop name.service
重启:service name restart ==> systemctl restart name.service
状体:service name status ==> systemctl status name.service
条件式重启:service name condrestart ==> systemctl try-restart name.service
重载或重启服务:systemctl reload-or-restart name.service
重载或条件式重启服务:systemctl reload-or-try-restart name.service
禁止设定为开机自启:systemctl mask name.service
取消禁止设定为开机自启:systemctl unmask name.service

查看某服务当前激活与否的状态:systemctl is-active name.service

查看所有已经激活的服务:systemctl list-units --type service
查看所有服务:systemctl list-units --type service --all

chkconfig命令的对应关系:
    设定服务开机自启动:chkconfig name on ==> systemctl enable name.service
    禁止:chkconfig name off ==> systemctl disable name.service
    查看所有服务的开机自启状态:chkconfig --list ==> systemctl list-unit-files --type service
    查看服务是否开机自启:systemctl is-enabled name.service

查看服务启动的依赖关系:
    systemctl list-dependences name.service

target units:
    unit配置文件:以.target结尾,

运行级别:
    0:runlevel0.target,poweroff.target
    1:runlevel1.target,rescue.target
    2:runlevel2.target,multi-user.target
    3:runlevel3.target,multi-user.target
    4:runlevel4.target,multi-user.target
    5:runlevel5.target,graphical.target
    6:runlevel6.target,reboot.target

级别切换:
    init N  ==> systemctl isolate name.target

查看级别:
    systemctl list-units --type target

获取默认运行级别:
    /etc/inittab  ==> systemctl get-default

修改默认级别:
    /etc/inittab ==> systemctl set-default name.target

切换至紧急救援模式:
    systemctl rescue
切换至emergency模式:
    systemctl emergency

其他常用命令:
    关机:systemctl halt、systemctl poweroff
    重启:systemctl reboot
    挂起:systemctl suspend
    快照:systemctl hibernate
    快照并挂起:systemctl hybrid-sleep

Target 与 SysV-init 进程的主要区别:

  • 默认的 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 目录里面的修改可以覆盖原始设置

unit 依赖关系
在 Systemd 中,Unit 之间可以建立依赖关系,以确保它们按照正确的顺序启动和停止。以下是 Unit 之间依赖关系的几种类型:

  • Requires:表示 Unit A 依赖于 Unit B,如果 Unit B 无法启动,则 Unit A 也无法启动。
  • Wants:表示 Unit A 希望依赖于 Unit B,但是如果 Unit B 无法启动,Unit A 仍然可以启动。
  • RequiresOverridable:与 Requires 类似,但是允许在启动时覆盖依赖的 Unit,例如在容器中运行时。
  • BindsTo:表示 Unit A 依赖于 Unit B,如果 Unit B 停止运行,则 Unit A 也会被停止。
  • PartOf:表示 Unit A 是 Unit B 的一部分,如果 Unit B 停止运行,则 Unit A 也会被停止。
  • Conflicts:表示 Unit A 与 Unit B 冲突,如果 Unit B 正在运行,则 Unit A 无法启动。
unit 文件:通常分成三段:[unit][service][install]
  • Unit 段:此部分所有 Unit 文件通用,用来定义 Unit 的元数据、配置以及与其他 Unit 的关系,Description 描述 Unit 文件信息,Documentation 表示指定服务的文档,Condition 表示服务启动的条件,有些 Unit 还包含 wants、before、after、require 字段,这些表示服务的一个依赖关系。
  • Install 段:此部分所有 Unit 文件通用,通常指定运行目标的 target,使得服务在系统启动时自动运行。Wantedby、RequiredBy 与 Unit 段 Wants 字段类似,表示依赖关系,Alias 字段表示启动运行时使用的别名。
  • service 段:服务(Service)类型的 Unit 文件特有的字段,用于定义服务的具体管理和执行动作。其中包括 Type 字段,定义进程的行为,例如使用 fork()启动,使用 dbus 启动等等;ExecStart、ExecStartPre、ExecStartPos、ExecReload、ExecStop 分别表示启动当前服务执行的命令、启动当前服务之前执行的命令、启动当前服务之后启动的命令、重启当前服务时执行的命令、停止当前服务时执行的命令。

Unit 段参数

  • Description:描述这个 Unit 文件的信息
  • Documentation:指定服务的文档,可以是一个或多个文档的 URL 路径
  • Requires:依赖的其它 Unit 列表,列在其中的 Unit 模板会在这个服务启动时的同时被启动。并且,如果其中任意一个服务启动失败,这个服务也会被终止
  • Wants:与 Requires 相似,但只是在被配置的这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
  • After:与 Requires 相似,但是在后面列出的所有模块全部启动完成以后,才会启动当前的服务
  • Before:与 After 相反,在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
  • Binds To:与 Requires 相似,失败时失败,成功时成功,但是在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
  • Part Of:一个 Bind To 作用的子集,仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
  • OnFailure:当这个模板启动失败时,就会自动启动列出的每个模块
  • Conflicts:与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然

Install 段参数
这部分配置的目标模块通常是特定运行目标的 .target 文件,用来使得服务在系统启动时自动运行。这个区段可以包含三种启动约束:

  • WantedBy:和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中,如 /etc/systemd/system/multi-user.target.wants/
  • RequiredBy:和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中
  • Also:当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
  • Alias:当前 Unit 可用于启动的别名

Service 段参数
用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段分为服务生命周期和服务上下文配置两个方面

服务生命周期控制相关

  • Type:定义启动时的进程行为,它有以下几种值:
    • Type=simple:默认值,执行ExecStart指定的命令,启动主进程
    • Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
    • Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
    • Type=dbus:当前服务通过D-Bus启动
    • Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
    • Type=idle:若有其他任务执行完毕,当前服务才会运行
  • RemainAfterExit:值为 true 或 false(默认)。当配置为 true 时,Systemd 只会负责启动服务进程,之后即便服务进程退出了,Systemd 也仍然会认为这个服务还在运行中。这个配置主要是提供给一些并非常驻内存,而是启动注册后立即退出,然后等待消息按需启动的特殊类型服务使用的。
  • ExecStart:启动当前服务的命令
  • ExecStartPre:启动当前服务之前执行的命令
  • ExecStartPost:启动当前服务之后执行的命令
  • ExecReload:重启当前服务时执行的命令
  • ExecStop:停止当前服务时执行的命令
  • ExecStopPost:停止当其服务之后执行的命令
  • RestartSec:自动重启当前服务间隔的秒数
  • Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括 always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
  • TimeoutStartSec:启动服务时等待的秒数,这一配置对于使用 Docker 容器而言显得尤为重要,因其第一次运行时可能需要下载镜像,严重延时会容易被 Systemd 误判为启动失败杀死。通常,对于这种服务,将此值指定为 0,从而关闭超时检测
  • TimeoutStopSec:停止服务时的等待秒数,如果超过这个时间仍然没有停止,Systemd 会使用 SIGKILL 信号强行杀死服务的进程
  • KillMode:定义 Systemd 如何停止 sshd 服务。
    • control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
    • process:只杀主进程
    • mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
    • none:没有进程会被杀掉,只是执行服务的 stop 命令。

服务上下文配置相关

  • Environment:为服务指定环境变量
  • EnvironmentFile:指定加载一个包含服务所需的环境变量的列表的文件,文件中的每一行都是一个环境变量的定义,该文件内部的key=value键值对,可以用$key的形式,在当前配置文件中获取
  • Nice:服务的进程优先级,值越小优先级越高,默认为 0。其中 -20 为最高优先级,19 为最低优先级
  • WorkingDirectory:指定服务的工作目录
  • RootDirectory:指定服务进程的根目录(/ 目录)。如果配置了这个参数,服务将无法访问指定目录以外的任何文件
  • User:指定运行服务的用户
  • Group:指定运行服务的用户组
  • MountFlags:服务的 Mount Namespace 配置,会影响进程上下文中挂载点的信息,即服务是否会继承主机上已有挂载点,以及如果服务运行执行了挂载或卸载设备的操作,是否会真实地在主机上产生效果。可选值为 shared、slaved 或 private
    • shared:服务与主机共用一个 Mount Namespace,继承主机挂载点,且服务挂载或卸载设备会真实地反映到主机上
    • slave:服务使用独立的 Mount Namespace,它会继承主机挂载点,但服务对挂载点的操作只有在自己的 Namespace 内生效,不会反映到主机上
    • private:服务使用独立的 Mount Namespace,它在启动时没有任何任何挂载点,服务对挂载点的操作也不会反映到主机上
  • LimitCPU / LimitSTACK / LimitNOFILE / LimitNPROC 等:限制特定服务的系统资源量,例如 CPU、程序堆栈、文件句柄数量、子进程数量等
  • 日志相关类,这里输出到journal,否则默认syslog

Unit 文件占位符
在 Unit 文件中,有时会需要使用到一些与运行环境有关的信息,例如节点 ID、运行服务的用户等。这些信息可以使用占位符来表示,然后在实际运行被动态地替换实际的值。

  • %n:完整的 Unit 文件名字,包括 .service 后缀名
  • %p:Unit 模板文件名中 @ 符号之前的部分,不包括 @ 符号
  • %i:Unit 模板文件名中 @ 符号之后的部分,不包括 @ 符号和 .service 后缀名
  • %t:存放系统运行文件的目录,通常是 “run”
  • %u:运行服务的用户,如果 Unit 文件中没有指定,则默认为 root
  • %U:运行服务的用户 ID
  • %h:运行服务的用户 Home 目录,即 %{HOME} 环境变量的值
  • %s:运行服务的用户默认 Shell 类型,即 %{SHELL} 环境变量的值
  • %m:实际运行节点的 Machine ID,对于运行位置每个的服务比较有用
  • %b:Boot ID,这是一个随机数,每个节点各不相同,并且每次节点重启时都会改变
  • %H:实际运行节点的主机名
  • %v:内核版本,即 “uname -r” 命令输出的内容
  • %%:在 Unit 模板文件中表示一个普通的百分号

服务的生命周期
当一个新的 Unit 文件被放入 /etc/systemd/system/ 或 /usr/lib/systemd/system/ 目录中时,它是不会被自识识别的。
在 Systemd 中,一个服务的生命周期包括以下几个阶段:

  • 加载阶段:Systemd 加载服务的 Unit 文件,并根据配置启动或禁止服务。
  • 准备阶段:Systemd 准备服务的启动环境,包括设置环境变量、创建所需目录、检查依赖关系等操作。
  • 启动阶段:Systemd 启动服务,执行服务的启动命令或程序,并记录服务的 PID。
  • 运行阶段:服务正常运行期间,Systemd 监视服务的状态,并记录日志、处理信号等操作。
  • 停止阶段:当服务需要停止时,Systemd 发送 stop 信号给服务进程,并等待服务进程退出。
  • 停止后处理阶段:当服务进程退出后,Systemd 执行服务的停止后处理命令或程序,并记录服务的退出状态。
  • 卸载阶段:当服务不再需要时,Systemd 卸载服务的 Unit 文件,并清理相关的运行时文件和日志。

除了以上阶段,Systemd 还提供了其他的功能,例如自动重启、服务状态查询、依赖关系管理等。通过 Systemd 的管理,可以更方便地管理和监控系统服务的运行状态。

服务的激活

  • systemctl enable:在 /etc/systemd/system/ 建立服务的符号链接,指向 /usr/lib/systemd/system/ 中
  • systemctl start:依次启动定义在 Unit 文件中的 ExecStartPre、**ExecStart **和 **ExecStartPost **命令

服务的启动和停止

  • systemctl start:依次启动定义在 Unit 文件中的 ExecStartPre、ExecStart 和 ExecStartPost 命令
  • systemctl stop:依次停止定义在 Unit 文件中的 ExecStopPre、ExecStop 和 ExecStopPost 命令
  • systemctl restart:重启服务
  • systemctl kill:立即杀死服务
服务的开机启动和取消
  • systemctl enable:除了激活服务以外,也可以置服务为开机启动
  • systemctl disable:取消服务的开机启动

服务的修改和移除

  • systemctl daemon-reload:Systemd 会将 Unit 文件的内容写到缓存中,因此当 Unit 文件被更新时,需要告诉 Systemd 重新读取所有的 Unit 文件
  • systemctl reset-failed:移除标记为丢失的 Unit 文件。在删除 Unit 文件后,由于缓存的关系,即使通过 daemon-reload 更新了缓存,在 list-units 中依然会显示标记为 not-found 的 Unit。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/572890.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

源代码开发企业的防泄密该怎么做

在源代码开发企业中&#xff0c;保护产品的知识产权和源代码安全是至关重要的。尤其是在面对Java等易被反编译的语言时&#xff0c;加密和保护源代码就显得尤为重要。针对这一挑战&#xff0c;SDC沙盒提供了一系列全面的解决方案&#xff0c;为企业源代码的安全保驾护航。 源代…

BSV区块链协会上线首个版本的ARC交易处理器

​​发表时间&#xff1a;2024年3月28日 BSV区块链协会近期上线了首个版本的ARC交易处理器。ARC是一项区块链交易处理服务&#xff0c;能在通过P2P网络广播交易之前验证并存储相关的交易。一旦新区块被挖出&#xff0c;一条与该交易相关的Merkle路径将被发回给交易发起者作为确…

JavaScript-4.正则表达式、BOM

正则表达式 正则表达式包含在"/"&#xff0c;"/"中 开始与结束 ^ 字符串的开始 $ 字符串的结束 例&#xff1a; "^The"&#xff1a;表示所有以"The"开始的字符串&#xff08;"There"、"The cat"等&#x…

JavaSE-14笔记【反射机制(+2024新)】

文章目录 1.反射机制概述2.获取Class的四种方式3.通过反射机制实例化对象*4.反射机制结合配置文件灵活实例化对象*5.java.lang.reflect.Field5.1反编译类中的所有字段/属性5.2 通过反射机制给属性赋值* 6.java.lang.reflect.Method6.1反编译类中的所有方法6.2 通过反射机制调用…

六个月滴滴实习:轻松、舒心又高薪!

不久前&#xff0c;一位在滴滴后端研发部门实习了六个月的小伙伴在牛客网上分享了他的实习体验&#xff0c; 作者详细描述了他在滴滴的实习生活。 从他的叙述中&#xff0c;我们可以感受到与其他互联网公司相比&#xff0c;滴滴的工作环境显得相对轻松和舒适。 他提到&#x…

Spring Boot-基础操作,常用工具,配置文件

lombok工具 首先将lombok的依赖引入 Lombok是一个实用的Java类库,能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率。 日志操作 自定义日志打印 有以下两步&#xff1a; 在一个类中先获…

Https协议原理剖析【计算机网络】【三种加密方法 | CA证书 】

目录 一&#xff0c;fidler工具 前提知识 二&#xff0c;Https原理解析 1. 中间人攻击 2. 常见的加密方式 1&#xff09;. 对称加密 2&#xff09;. 非对称加密 对称加密 4&#xff09;. CA证书 1. 数据摘要 3. 数字签名 CA证书 理解数据签名 存在的安全疑问&am…

根据当年节假日和非工作时间计算请假时间-获取每个月的节假日,计算每个月的工作日时间进度,节假日每年更新

根据需求请假时间要排除法定节假日和非工作时间 1.获取当年的节假日 节假日是每年更新的&#xff0c;没有固定接口&#xff0c;需要手动录入 个人根据官方的节假日整理了当年的所有节假日&#xff0c;可以根据个人需求进行修改 // 获取每个月的节假日&#xff0c;如果当月没…

数据结构入门——排序(代码实现)(下)

int GetMidi(int* a, int left, int right) {int mid (left right) / 2;// left mid rightif (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right]) // mid是最大值{return left;}else{return right;}}else // a[left] > a[mid…

c++二叉树的进阶--二叉搜索树

1. 二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的左…

R-Tree与其他空间索引结构的对比

文章目录 R-Tree vs Quadtree/OctreeR-Tree vs kd-TreeR-Tree vs BSP TreeR-Tree vs Hilbert R-Tree总结Python: 使用rtree库实现R-TreeJavaScript: 使用rbush库实现kd-Tree R-Tree是一种广泛使用的空间索引结构&#xff0c;尤其适用于处理多维空间数据。然而&#xff0c;还有其…

电脑上怎么调照片尺寸?怎么压缩图片为144×144

在一些社交媒体平台通常要求用户上传头像&#xff0c;并对其进行裁剪和调整大小&#xff0c;144x144像素是常见的头像尺寸之一&#xff0c;适合在社交媒体上展示个人头像或者小图标&#xff0c;为了可以保证图片的画质&#xff0c;我们尽量会选择专业的图片处理工具来完成操作。…

OpenAI推出强化企业级安全与成本管理新功能

欢迎大家在 GitHub 上 Star 我们&#xff1a; 分布式全链路因果学习系统 OpenASCE: https://github.com/Open-All-Scale-Causal-Engine/OpenASCE 大模型驱动的知识图谱 OpenSPG: https://github.com/OpenSPG/openspg 大规模图学习系统 OpenAGL: https://github.com/TuGraph-…

探索在Apache SeaTunnel上使用Hudi连接器,高效管理大数据的技术

Apache Hudi是一个数据湖处理框架&#xff0c;通过提供简单的方式来进行数据的插入、更新和删除操作&#xff0c;Hudi能够帮助数据工程师和科学家更高效地处理大数据&#xff0c;并支持实时查询。 支持的处理引擎 Spark Flink SeaTunnel Zeta 主要特性 批处理 流处理 精确一次性…

Linux——(grep指令及zip/tar压缩指令)

1.grep指令 语法&#xff1a; grep【选项】查找字符串 文件 功能&#xff1a; 在文件中搜索字符串&#xff0c;将找到的行打印出来 常用选项&#xff1a; -i &#xff1a;忽略大小写&#xff0c;所以大小写视为相同 -n &#xff1a; 顺便输出行号 -v &#xff1a;反向选择&…

DDD领域驱动设计总结和C#代码示例

DDD&#xff08;领域驱动设计&#xff09;是一种软件设计方法&#xff0c;它强调以业务领域为核心来驱动软件的设计和开发。 DDD 的设计初衷是为了解决复杂业务领域的设计和开发问题&#xff0c;它提供了一套丰富的概念和模式&#xff0c;帮助开发者更好地理解和建模业务领域&…

【管理咨询宝藏88】556页!公司经营分析内部培训

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏88】556页&#xff01;公司经营分析内部培训 【格式】PDF版本 【关键词】经营分析、内部培训、多业务分析 【核心观点】 - 非常全面和详细的公…

Composer初次接触

php一直都是简单处理一下单片机的后台服务&#xff0c;没什么深入研究 今天安装一个 php composer.phar require qiniu/php-sdkComposer完全不懂&#xff0c;照着一试&#xff0c;就报错了 - topthink/think-installer v1.0.12 requires composer-plugin-api ^1.0 -> found…

Python爬虫入门指南--爬虫技术的由来、发展与未来--实战课程大赠送

爬虫&#xff0c;也称为网络爬虫或网络蜘蛛&#xff0c;是一种自动化程序&#xff0c;专门用于遍历互联网并收集数据。这种技术的起源、发展和未来都与互联网紧密相连&#xff0c;并在信息检索、数据挖掘等多个领域发挥着不可或缺的作用。 "免费IP池大放送&#xff01;助…

【汇编语言】流程转移和子程序

【汇编语言】流程转移和子程序 文章目录 【汇编语言】流程转移和子程序前言一、“转移”综述二、操作符offset三、jmp指令jmp指令——无条件转移jmp指令&#xff1a;依据位移进行转移两种段内转移远转移&#xff1a;jmp far ptr 标号转移地址在寄存器中的jmp指令转移地址在内存…