linux服务篇-Systemctl

37 篇文章 0 订阅

Systemd 简介

Systemd 是一系列工具的集合,其作用也远远不仅是启动操作系统,它还接管了后台服务、结束、状态查询,以及日志归档、设备管理、电源管理、定时任务等许多职责,并支持通过特定事件(如插入特定 USB 设备)和特定端口数据触发的 On-demand(按需)任务。

Systemd 的后台服务还有一个特殊的身份——它是系统中 PID 值为 1 的进程。

Systemctl官方手册:https://www.freedesktop.org/software/systemd/man/systemctl.html#

Systemd官方手册:https://www.freedesktop.org/software/systemd/man/systemd.html#

 

systemd和systemctl

我们提到systemctl就一定需要知道systemd,因为Linux 服务管理有两种方式service和systemctl。而systemd是Linux系统最新的初始化系统(init),作用是提高系统的启动速度,尽可能启动较少的进程,尽可能更多进程并发启动,systemd对应的进程管理命令就是systemctl。值得一提的是,systemctl命令兼容了service哦。

 

这里咱们梳理一下systemd这个启动服务管理机制有哪些好处(也就是使用systemctl相关命令的好处啦)。

  1. 平行处理所有服务,加速开机流程:旧的init启动脚本(System V的那个)是“一项一项任务依序启动”的模式,因此不相依的服务也是得要一个一个的等待。而systemd可以让所有的服务同时启动,毕竟目前我们的硬件主机系统与操作系统几乎都支持多核心架构,因此你会发现到,系统启动的速度变快了;
  2. 一经请求就响应的on-demand启动方式:systemd仅有一只systemd服务,搭配systemctl指令进行处理,无须其他额外的指令来支持。不像systemV还要init,chkconfig,service...等等指令。此外,systemd由于常驻内存,因此任何请求(on-demand)都可以立即处理后续的daemon启动的任务;
  3. 服务关联性的自我检查:由于systemd可以自行进行服务关联性的检查,因此如果B服务的启动前提是A服务,那当你在没有启动A服务的情况下仅手动启动B服务时,systemd会自动帮你启动A服务;
  4. 根据daemon功能分类:systemd旗下管理的服务非常多,为了理清所有服务的功能,因此,首先systemd先定义所有的服务为一个服务单位(这里单位叫“unit”,挺重要的,后面详细说),并将该unit分类到不同的服务类型(type)中。systemd将服务单位(unit)区分为service,socket,target,path,snapshot,timer等多种不同的类型(type);
  5. 将多个daemons集合成为一个群组:systemd将许多的功能集合成为一个所谓的target项目,这个项目主要用于设计操作环境的创建,所以集合了许多的daemons(执行某个target就是执行多个daemon);
  6. 向下相容旧有的init服务脚本:基本上,systemd是可以兼容init的启动脚本,因此,旧的init启动脚本也能够通过systemd来管理,当然了,这里仅限于不使用systemd的某些高级功能;

 

任务

旧命令

新命令

使某服务自动启动

chkconfig --level 3 httpd on

systemctl enable httpd.service

使某服务不自动启动

chkconfig --level 3 httpd off

systemctl disable httpd.service

检查服务状态

service httpd status

systemctl status httpd.service (服务详细信息)

systemctl is-active httpd.service (仅显示是否 Active)

显示所有已启动的服务

chkconfig --list

systemctl list-units --type=service

启动某服务

service httpd start

systemctl start httpd.service

停止某服务

service httpd stop

systemctl stop httpd.service

重启某服务

service httpd restart

systemctl restart httpd.service

对比表,以apache/httpd为例

systemd的优缺点

优点:

  1. 按需启动进程,减少系统资源消耗

Systemd 提供了 服务按需启动 的能力,使得特定的服务只有在真定被请求时才启动。

 

  1. 并行启动进程,提高系统启动速度

在 SysV-init 时代,将每个服务项目编号依次执行启动脚本。Ubuntu 的 Upstart 解决了没有直接依赖的启动之间的并行启动。而 Systemd 通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。对于用户自定义的服务,Systemd 允许配置其启动依赖项目,从而确保服务按必要的顺序运行。

 

  1. 使用 CGroup 监视和管理进程的生命周期

在 Systemd 之间的主流应用管理服务都是使用 进程树 来跟踪应用的继承关系的,而进程的父子关系很容易通过 两次 fork 的方法脱离。

而 Systemd 则提供通过 CGroup 跟踪进程关系,引补了这个缺漏。通过 CGroup 不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期。

 

  1. 统一管理服务日志

Systemd 是一系列工具的集合, 包括了一个专用的系统日志管理服务:Journald。这个服务的设计初衷是克服现有 Syslog 服务的日志内容易伪造和日志格式不统一等缺点,Journald 用 二进制格式 保存所有的日志信息,因而日志内容很难被手工伪造。Journald 还提供了一个 journalctl 命令来查看日志信息,这样就使得不同服务输出的日志具有相同的排版格式, 便于数据的二次处理。

 

  1. 支持快照和系统恢复

 

缺点:

  1. 过于复杂,与操作系统的其他部分强耦合,违反"keep simple, keep stupid"的Unix 哲学("简单原则"----尽量用简单的方法解决问题----是"Unix哲学"的根本原则。这也就是著名的KISS(keep it simple, stupid),意思是"保持简单和笨拙"。)

systemd架构

d21280828b054030861529b61c2dc1fa.png

systemd的配置文件目录

Unit 文件按照 Systemd 约定,应该被放置指定的三个系统目录之一中。这三个目录是有优先级的,如下所示,越靠后的优先级越高。因此,在三个目录中有同名文件的时候,只有优先级最高的目录里的那个文件会被使用。

    /usr/lib/systemd/system/(centos),/etc/systemd/system(Ubuntu):每个服务最主要的启动脚本的配置放在这,有点类似以前的/etc/init.d;

    /run/systemd/system/:系统执行过程中所产生的服务脚本所在目录,这些脚本的优先级要比/usr/lib/systemd/system/高;

    /etc/systemd/system/:管理员根据主机系统的需求所创建的执行脚本所在目录,执行优先级比/run/systemd/system/高;

从上面的功能及优先级次序,我们可以知道,/etc/systemd/system/目录下的相关配置,决定系统了会不会执行某些服务,所以该目录下面一般放着一大堆链接文件,指向目录 /usr/lib/systemd/system/。而/usr/lib/systemd/system/下,则放着实际执行的systemd启动脚本配置文件。因此如果你想要修改某个服务启动的设置,应该去/usr/lib/systemd/system/下面修改。/etc/systemd/system/仅是链接到正确的执行脚本配置文件而已。所以想要看执行脚本设置,应该就得要到/usr/lib/systemd/system/去查阅。

/etc/default/ 这个目录中放置很多服务默认的配置文件。

/var/lib/ 一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中,比如 docker 相关的数据文件就放在这个目录下。

/run/ 这个目录放置了好多服务运行时的临时数据,比如 lock file 以及 PID file 等等。

Unit

Unit(单元|服务):Systemd 可以管理所有系统资源,不同的资源统称为 Unit(单位)。

在 Systemd 的生态圈中,Unit 文件统一了过去各种不同系统资源配置格式,例如服务的启/停、定时任务、设备自动挂载、网络配置、虚拟内存配置等。而 Systemd 通过不同的文件后缀来区分这些配置文件。

将系统资源划分为12类,将每个系统资源称为一个 Unit。Unit 是 Systemd 管理系统资源的基本单位,使用一个 Unit File 作为 Unit 的单元文件,Systemd 通过单元文件控制 Unit 的启动,例如,MySQL服务被 Systemd 视为一个 Unit,使用一个 mysql.service 作为启动配置文件。

Unit 和 Target

Unit 是 Systemd 管理系统资源的基本单元,可以认为每个系统资源就是一个 Unit,并使用一个 Unit 文件定义。在 Unit 文件中需要包含相应服务的描述、属性以及需要运行的命令。

Target 是 Systemd 中用于指定系统资源启动组的方式,相当于 SysV-init 中的运行级别。

简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于”状态点”,启动某个 Target 就好比启动到某种状态。

 

Unit File类型

Unit File(单元文件|配置文件):单元文件中包含该单元的描述、属性、启动命令等

Systemd 将系统资源划分为12类,对应12种类型的单元文件。

系统资源类型

单元文件扩展名

单元文件描述

Service

.service

封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件, 为了与 SysV 兼容,我们不仅支持我们自己的服务配置文件,而且还能够读取经典的 SysV init 脚本,特别是我们解析 LSB 标头(如果存在)。

Target

.target

 定义 target 信息及依赖关系,一般仅包含 Unit 段。它本身并不实际做任何事情,它只是引用其他单元,从而可以一起控制。这方面的例子是:multi-user.target,它是一个在经典 SysV 系统上基本上扮演运行级别 5 角色的目标

Device

.device

 对于 /dev 目录下的硬件设备,主要用于定义设备之间的依赖关系, 如果设备通过 udev 规则为此标记,它将在 systemd 中作为device unit公开。使用udev设置的属性可用作配置源来设置设备单元的依赖关系。

Mount

.mount

 定义文件系统的挂载点,可以替代过去的 /etc/fstab 配置文件

Automount

.automount

用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务,每个自动挂载 单元都有一个匹配的挂载单元,一旦访问自动挂载目录,它就会启动(即挂载)。

Path

.path

 用于监控指定目录或文件的变化,并触发其它 Unit 运行

Scope

.scope

这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息

Slice

.slice

用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件

Snapshot

.snapshot

用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照,可以切回某个快照

Socket

.socket

监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动

Swap

.swap

定义一个用户做虚拟内存的交换分区

Timer

.timer

用于配置在特定时间触发的任务,替代了 Crontab 的功能

对于操作单元文件的命令,如果缺省扩展名,则默认.service扩展名

而操作 target 的命令,例如 isolate,则默认.target扩展名.

所有这些单元之间都可以有依赖关系(正面和负面,即“要求”和“冲突”):设备可以依赖于服务,这意味着一旦设备可用,就会启动某个服务。挂载对挂载它们的设备具有隐式依赖关系。挂载还获得对作为其前缀的挂载的隐式依赖项(即挂载/home/lennart隐式地将依赖项添加到挂载/home)等等。

主要服务功能类型详细说明

.service:一般服务类型(service unit):主要是系统服务,包括服务器本身所需要的本机服务以及网络服务,比较经常被使用到的服务大多是这种类型,所以,这也是最常见的类型。

.socket:内部程序数据交换的插槽服务(socketunit):主要是IPC(Inter-processcommunication)的传输信息插槽(socketfile)功能。这种类型的服务通常在监控信息传递的插槽档,当有通过此插槽传递信息请求链接服务的时候,就依据当时的状态将该用户的请求传送到对应的daemon,若daemon尚未启动,则启动该daemon后再传送用户的请求。使用socket类型的服务一般是比较不会被用到的服务,因此在开机时通常会稍微延迟启动的时间。一般用于本机服务比较多,例如我们的图形界面很多的软件都是通过socket来进行本机程序数据交换的行为。

.target:执行环境类型(target unit):其实是一群unit的集合,例如multi-user.target其实就是一堆服务的集合。.target定义了一些基础的组件,供.service文件调用。

.mount:文件系统挂载相关的服务(automount unit/mount unit):例如来自网络的自动挂载、NFS文件系统挂载等与文件系统相关性较高的程序管理。.mount文件定义了一个挂载点,[Mount]节点里配置了What,Where,Type三个数据项。等同于以下命令:mount -t hugetlbfs /dev/hugepages hugetlbfs

.path:监测特定文件或目录类型(path unit):某些服务需要监测某些特定的目录来提供序列服务,例如最常见的打印服务,就是通过监测打印序列目录来启动打印功能。这时就得要.path的服务类型支持。

.timer:循环执行的服务(timer unit):这个东西有点类似anacrontab,不过是由systemd主动提供的,比anacrontab更加有弹性。

.snapshot: 类似于target单元快照本身实际上不做任何事情,它们的唯一目的是引用其他单元。快照可用于保存/回滚 init 系统的所有服务和单元的状态。它主要有两个预期用例:允许用户临时进入特定状态,例如“紧急外壳”,终止当前服务,并提供一种简单的方法返回之前的状态,再次拉起所有临时拉动的服务下。并简化对系统挂起的支持:仍然有许多服务无法正确处理系统挂起,通常最好在挂起之前关闭它们,然后再恢复它们。

systemctl配置文件的设置

这里我们先查看一下service里面的内容,随便找了一个内容比较多的sshd.service,方便讲解,指令结果如下:

[root@desktop ~]# cat /usr/lib/systemd/system/sshd.service

[Unit]

Description=OpenSSH server daemon

Documentation=man:sshd(8) man:sshd_config(5)

After=network.target sshd-keygen.target

Wants=sshd-keygen.target

 

[Service]

Type=notify

EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config

EnvironmentFile=-/etc/sysconfig/sshd-permitrootlogin

EnvironmentFile=-/etc/sysconfig/sshd

ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY $PERMITROOTLOGIN

ExecReload=/bin/kill -HUP $MAINPID

KillMode=process

Restart=on-failure

RestartSec=42s

 

[Install]

WantedBy=multi-user.target

单元文件的语法来源于 XDG桌面入口配置文件.desktop文件

Unit 文件可以分为三个配置区段:

Unit 段:所有 Unit 文件通用,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系

Install 段:所有 Unit 文件通用,用来定义如何启动,以及是否开机启动

Service 段:服务(Service)类型的 Unit 文件(后缀为 .service)特有的,用于定义服务的具体管理和执行动作

单元文件中的区段名和字段名大小写敏感

每个区段内都是一些等号连接的键值对(键值对的等号两侧不能有空格)

 

其中三个部分分别是:

[Unit]:unit本身的说明,以及与其他相关联daemon的设置,包括在什么服务之后才启动此unit之类的设置值;

[Service],[Socket],[Timer],[Mount],[Path]等等:不同的unit type就得要使用相对应的设置项目,我们拿的是sshd.service来举例,所以这边就使用[Service]来设置。这个项目内主要在规范服务启动的脚本、环境配置文件文件名、重新启动的方式等等;

[Install]:这个项目就是将此unit安装到哪个target里面去;

 

至于配置文件内有些设置规则还是得要说明一下:

    1. 设置项目通常是可以重复的,例如我可以重复设置两个After在配置文件中,不过,后面的设置会取代前面的,因此,如果你想要将设置值归零,可以使用类似“After=”的设置,即该项目的等号后面什么都没有,就将该设置归零了(reset);
    2. 如果设置参数需要有“是/否”的项目(布尔值,boolean),你可以使用1,yes,true,on代表启动,用0,no,false,off代表关闭!随你喜好选择;
    3. 空白行、开头为#或;的那一行,都代表注解;

 

Unit段

[Unit]部分

设置参数

参数意义说明

Description

就是当我们使用 systemctl list-units 时,会输出给管理员看的简易说明,当然,使用systemctlstatus 输出的此服务的说明,也是这个项目。

Documentation

这个项目在提供管理员能够进行进一步的文件查询的功能,提供的文件可以是如下的数据:Documentation=http://www....

After

说明此 unit 是在哪个 daemon 启动之后才启动,基本上仅是说明服务启动的顺序而已,并没有强制要求里面的服务一定要启动后此unit才能启动。以 sshd.service 的内容为例,该文件提到 After 后面有network.target 以及 sshd-keygen.service ,但是若这两个 unit 没有启动而强制启动sshd.service 的话,那么 sshd.service 应该还是能够启动的,这与Requires 的设置是有差异的。

Before

与 After 的意义相反,是在什么服务启动前最好启动这个服务。不过这仅是规范服务启动的顺序,并非强制要求。

Requires

强依赖,明确的定义此 unit 需要在哪个 daemon 启动后才能够启动,就是设置服务的关联性,如果在此项设置的前导服务没有启动,那么此unit 就不会被启动。

Wants

弱依赖,与 Requires 刚好相反,规范的是这个 unit 之后最好还要启动什么服务,不过,并没有明确的规范,主要的目的是希望创建让使用者比较好操作的环境。因此,这个Wants后面接的服务如果没有启动,其实不会影响到这个unit 本身。

Conflicts

代表冲突的服务,即这个项目后面接的服务如果有启动,那么我们这个 unit 本身就不能启动,我们 unit 有启动,则此项目后的服务就不能启动,就是冲突性的检查。

Binds To

与 Requires 相似,失败时失败,成功时成功,但是在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启.

Part Of

一个 Bind To 作用的子集,仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动

OnFailure

当这个模板启动失败时,就会自动启动列出的每个模块

Service段

用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。

【启动类型】

说明这个 daemon 启动的方式,会影响到 ExecStart, 一般来说,有下面几种类型:

1、Type=simple :默认值,这个 daemon 主要由 ExecStart 接的指令串来启动,启动的进程为主进程 。启动后常驻于内存中。

服务进程不会 fork,如果该服务要启动其他服务,不要使用此类型启动,除非该服务是 socket 激活型。

2、Type=forking :ExecStart字段将以fork()方式从父进程创建子进程启动,创建后父进程会立即退出,子进程成为主进程。

通常需要指定PIDFile字段,以便 Systemd 能够跟踪服务的主进程。

对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。

由 ExecStart 启动的程序通过spawns 延伸出其他子程序来作为此 daemon 的主要服务。原生的父程序在启动结束后就会终止运行。传统的unit 服务大多属于这种项目,例如httpd 这个 WWW 服务,当 httpd 的程序因为运行过久因此即将终结了,则systemd 会再重新生出另一个子程序持续运行后,再将父程序删除。

3、Type=oneshot :与simple 类似,不过这个程序在工作完毕后就结束了,不会常驻在内存中。

适用于只执行一项任务、随后立即退出的服务

通常需要指定RemainAfterExit=yes字段,使得 Systemd 在服务进程退出之后仍然认为服务处于激活状态

4、Type=dbus :与 simple 类似,但这个 daemon 必须要在取得一个D-Bus的名称后,才会继续运行!因此设置这个项目时,通常也要设置BusName= 才行!

5、Type=notify:当前服务启动完毕会发出通知信号,通知 Systemd,然后 Systemd 再启动其他服务。

6、Type=idle :与 simple 类似,意思是,要执行这个daemon必须要所有的工作都顺利执行完毕后才会执行。这类的 daemon通常是开机到最后才执行即可的服务!比较重要的项目大概是simple,forking 与 oneshot 了!毕竟很多服务需要子程序(forking ),而有更多的动作只需要在开机的时候执行一次(oneshot ),例如文件系统的检查与挂载啊等等的。

【启动行为】

1、ExecStart:启动当前服务的命令,可以指定启动脚本的环境配置文件!例如 sshd.service 的配置文件写入到/etc/sysconfig/sshd 当中!你也可以使用 Environment= 后面接多个不同的Shell 变量来给予设置!

ExecStart=/bin/echo execstart1

ExecStart=

ExecStart=/bin/echo execstart2

顺序执行设定的命令,把字段置空,表示清除之前的值

2、ExecStartPre:启动当前服务之前执行的命令

3、ExecStartPost:启动当前服务之后执行的命令

4、ExecReload:重启当前服务时执行的命令,,与 systemctl reload 有关的指令行为

5、ExecStop:停止当前服务时执行的命令,与 systemctl stop 的执行有关,关闭此服务时所进行的指令。

6、ExecStopPost:停止当前服务之后执行的命令

7、RemainAfterExit:当前服务的所有进程都退出的时候,Systemd 仍认为该服务是激活状态。当设置为 RemainAfterExit=1 时,则当这个 daemon 所属的所有程序都终止之后,此服务会再尝试启动。这对于Type=oneshot 的服务很有帮助!

这个配置主要是提供给一些并非常驻内存,而是启动注册后立即退出,然后等待消息按需启动的特殊类型服务使用的

8、TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数,若这个服务在启动或者是关闭时,因为某些缘故导致无法顺利 “ 正常启动或正常结束” 的情况下,则我们要等多久才进入 “ 强制结束 ” 的状态!

注:所有的启动设置之前,都可以加上一个连词号(-),表示"抑制错误",即发生错误的时候,不影响其他命令的执行。比如,EnvironmentFile=-/etc/sysconfig/sshd(注意等号后面的那个连词号),就表示即使/etc/sysconfig/sshd文件不存在,也不会抛出错误。

【重启行为】

RestartSec:Systemd 重启当前服务间隔的秒数,与 Restart 有点相关性,如果这个服务被关闭,然后需要重新启动时,大概要sleep 多少时间再重新启动的意思。默认是 100ms (毫秒)。

KillMode:定义 Systemd 如何停止服务,可以是 process,control-group,none 的其中一种,如果是 process则daemon 终止时,只会终止主要的程序( ExecStart 接的后面那串指令),如果是control-group 时,则由此 daemon 所产生的其他control-group的程序,也都会被关闭。如果是 none 的话,则没有程序会被关闭喔!可能的值包括:

  1. control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
  2. process:只杀主进程(sshd 服务,推荐值)
  3. mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
  4. none:没有进程会被杀掉,只是执行服务的 stop 命令。

Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括:

  1. no(默认值):退出后不会重启
  2. on-success:只有正常退出时(退出状态码为0),才会重启
  3. on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启(守护进程,推荐值)
  4. on-abnormal:只有被信号终止和超时,才会重启(对于允许发生错误退出的服务,推荐值)
  5. on-abort:只有在收到没有捕捉到的信号终止时,才会重启
  6. on-watchdog:超时退出,才会重启
  7. always:不管是什么退出原因,总是重启

【上下文】

PIDFile:指向当前服务 PID file 的绝对路径。

User:指定运行服务的用户

Group:指定运行服务的用户组

EnvironmentFile:指定当前服务的环境参数文件。该文件内部的key=value键值对,可以用$key的形式,在当前配置文件中获取,例如 sshd.service 的配置文件写入到/etc/sysconfig/sshd 当中!你也可以使用 Environment= 后面接多个不同的Shell 变量来给予设置!

启动sshd,执行的命令是/usr/sbin/sshd -D $OPTIONS,其中的变量$OPTIONS就来自EnvironmentFile字段指定的环境参数文件。

Install 段

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

 

[Install]部分

设置参数

参数意义说明

WantedBy

和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中,如 “/etc/systemd/system/multi-user.target.wants/“,这个设置后面接的大部分是 *.targetunit !意思是,这个 unit 本是附挂在哪一个targetunit 下面的!一般来说,大多的服务性质 unit 都是附挂在multi-user.target下面!

RequiredBy

和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中

Also

当目前这个 unit 本身被 enable 时, Also 后面接的 unit 也请 enable。 也就是具有相依性的服务可以写在这里。

Alias

进行一个链接的别名的意思!当 systemctlenable 相关的服务时则此服务会进行链接文件的创建!以multi-user.target 为例,这个伙是用来作为默认操作环境default.target 的规划,因此当你设置成 default.target时,这个/etc/systemd/system/default.target 就会链接到/usr/lib/systemd/system/multi-user.target。

通过 systemctl list-units --type=target 命令可以获取当前正在使用的运行目标

# systemctl list-units --type=target

UNIT                   LOAD   ACTIVE SUB    DESCRIPTION

basic.target           loaded active active Basic System

cryptsetup.target      loaded active active Encrypted Volumes

getty.target           loaded active active Login Prompts

graphical.target       loaded active active Graphical Interface

local-fs-pre.target    loaded active active Local File Systems (Pre)

local-fs.target        loaded active active Local File Systems

multi-user.target      loaded active active Multi-User System

network-online.target  loaded active active Network is Online

network.target         loaded active active Network

nss-user-lookup.target loaded active active User and Group Name Lookups

paths.target           loaded active active Paths

remote-fs-pre.target   loaded active active Remote File Systems (Pre)

remote-fs.target       loaded active active Remote File Systems

slices.target          loaded active active Slices

sockets.target         loaded active active Sockets

sound.target           loaded active active Sound Card

swap.target            loaded active active Swap

sysinit.target         loaded active active System Initialization

time-sync.target       loaded active active System Time Synchronized

timers.target          loaded active active Timers

LOAD   = Reflects whether the unit definition was properly loaded.

ACTIVE = The high-level unit activation state, i.e. generalization of SUB.

SUB    = The low-level unit activation state, values depend on unit type.

20 loaded units listed. Pass --all to see loaded but inactive units, too.

To show all installed unit files use 'systemctl list-unit-files'.

 

Unit 文件占位符和模板

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 模板

在现实中,往往有一些应用需要被复制多份运行。例如,用于同一个负载均衡器分流的多个服务实例,或者为每个 SSH 连接建立一个独立的 sshd 服务进程。

Unit 模板文件的写法与普通的服务 Unit 文件基本相同,不过 Unit 模板的文件名是以 @ 符号结尾的。通过模板启动服务实例时,需要在其文件名的 @ 字符后面附加一个参数字符串。

示例:apache@.service

1、apache@.service 模板如下

[Unit]

Description=My Advanced Service Template

After=etcd.service docker.service

 

[Service]

TimeoutStartSec=0

ExecStartPre=-/usr/bin/docker kill apache%i

ExecStartPre=-/usr/bin/docker rm apache%i

ExecStartPre=/usr/bin/docker pull coreos/apache

ExecStart=/usr/bin/docker run --name apache%i -p %i:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND

ExecStartPost=/usr/bin/etcdctl set /domains/example.com/%H:%i running

ExecStop=/usr/bin/docker stop apache1

ExecStopPost=/usr/bin/docker rm apache1

ExecStopPost=/usr/bin/etcdctl rm /domains/example.com/%H:%i

 

[Install]

WantedBy=multi-user.target

2、启动 Unit 模板的服务实例

在服务启动时需要在 @ 后面放置一个用于区分服务实例的附加字符参数,通常这个参数用于监控的端口号或控制台 TTY 编译号。

# systemctl start apache@8080.service

Systemd 在运行服务时,总是会先尝试找到一个完整匹配的 Unit 文件,如果没有找到,才会尝试选择匹配模板。例如上面的命令,System 首先会在约定的目录下寻找名为 apache@8080.service 的文件,如果没有找到,而文件名中包含 @ 字符,它就会尝试去掉后缀参数匹配模板文件。对于 apache@8080.service,systemd 会找到 apache@.service 模板文件,并通过这个模板文件将服务实例化。

 

自定义服务

在 /usr/lib/systemd/system 下新建服务脚本

vim /usr/lib/systemd/system/zdy.service

 

[Unit]

Description=描述

Environment=环境变量或参数(系统环境变量此时无法使用)

After=network.target

 

[Service]

Type=forking

EnvironmentFile=所需环境变量文件或参数文件

ExecStart=启动命令(需指定全路径)

ExecStop=停止命令(需指定全路径)

User=以什么用户执行命令

 

[Install]

WantedBy=multi-user.target

新建完成后设置自启动

# 添加或修改配置文件后,需要重新加载

systemctl daemon-reload

 

# 设置自启动,实质就是在 /etc/systemd/system/multi-user.target.wants/ 添加服务文件的链接

systemctl enable zdy

在安装新服务包后,进入安装包路径查找.service单位文件

# find . -name *service*

# cp unitservice.service /usr/lib/systemd/system/

# chmod 644 /usr/lib/systemd/system/unitservice.service

# systemctl list-unit-files |grep unitservice

# systemctl enable unitservice && systemctl start unitservice

 

 

服务状态

这里我们可以先试用下面这个指令查看一下atd服务的当前状态,指令和结果如下:

[root@desktop ~]# systemctl status atd.service

● atd.service - Deferred execution scheduler

   Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)

   Active: active (running) since Wed 2021-07-28 09:53:18 CST; 1h 59min ago

     Docs: man:atd(8)

 Main PID: 1592 (atd)

    Tasks: 1

   Memory: 280.0K

   CGroup: /system.slice/atd.service

           └─1592 /usr/sbin/atd -f

 

7月 28 09:53:18 desktop.example.com systemd[1]: Started Deferred execution scheduler.

第一行是对 unit 的基本描述。点("●")在支持的终端上使用颜色来概述单位状态。白色表示“未激活”或“失效”状态。红色表示“失败”或“错误”状态,绿色表示“激活”、“重新加载”或“激活”状态。

 

第二行中的 Loaded 描述操作系统启动时会不会启动这个服务,enabled 表示开机时启动,disabled 表示开机时不启动。而启动该服务的配置文件路径为:/usr/lib/systemd/system/atd.service。
如果单元已经加载到内存中,输出中的“Loaded:”行将显示“Loaded”。“Loaded:”的其他可能值包括:“error”(如果在加载它时出现了问题),“not-found”(如果这个单元没有找到单元文件),“bad-setting”(如果基本单元文件设置不能被解析),以及“masking”(如果单元文件已经被屏蔽)。除了显示单元文件的路径外,这一行还将显示启用状态。启用命令在启动时启动。请参阅is-enabled命令文档中可能的启用状态的完整表——包括“mask”的定义。

 

第三行 中的 Active 描述服务当前的状态,active (running) 表示服务正在运行中。如果是 inactive (dead) 则表示服务当前没有运行。后面则是服务的启动时间。“Active:”行显示活动状态。取值通常为“active”或“inactive”。激活可能意味着启动、绑定、插入等等,这取决于单元类型。该单元还可能处于状态变化的过程中,报告“激活”或“失效”状态。当服务以某种方式失败时,比如崩溃、带错误代码退出或超时,就会进入一个特殊的“失败”状态。如果进入失败状态,将记录原因,以供以后参考。

 

第四行的 Docs 提供了在线文档的地址。

下面的 Main PID 表示进程的 ID,接下来是任务的数量,占用的内存和 CPU 资源。

再下面的 Cgroup 描述的是 cgrpup 相关的信息,笔者会在后续的文章中详细的介绍。

最后是输出的日志信息。

看到绿色高亮的那个没有,这就是当前服务的状态。那么服务有哪几种常见的状态呢,这里列举说明一下。

    active(running):正有一只或多只程序正在系统中执行的意思;

    active(exited):仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行;举例来说,开机或者是挂载时才会进行一次的 quotaon 功能,就是这种模式! Quotaon 不需要一直执行,只在执行一次之后,就交给文件系统去自行处理。通常用 bash shell 写的小型服务,大多是属于这种类型。

    active(waiting):正在执行当中,不过还需要等待其他的事件才能继续处理;举例来说,打印的相关服务就是这种状态。

    inactive:这个服务目前没有运行;

    dead:程序已经清除;

上面是运行结果中,黄底红字的地方,那个是啥?那个其实是这只服务程序的启动状态,也分为一下几种状态。

    enabled:这个daemon将在开机时被执行;

    disabled:这个daemon在开机时不会被执行;

    static:这个daemon不可以自己启动(enable不可),不过可能会被其他的enabled 的服务来唤醒(关联属性的服务);

    mask:这个daemon无论如何都无法被启动,因为已经被强制注销(非删除),可通过systemctl unmask方式改回原本状态;

 

常用指令

systemctl --version  #查看systemctl版本号

systemctl #范列出系统上面有启动的unit

systemctl list-units   #列出所有启动unit

    systemctl list-unit-files #列出所有已经安装的unit有哪些

    systemctl list-units --type=service --all  #列出类型为service的所有项目,不论启动与否

systemctl get-default  #输入目前机器默认的模式,如图形界面模式或者文本模式

systemctl set-default multi-user.target  #设置指定的target为默认的运行级别

    systemctl isolate multi-user.target  #将目前的操作环境改为纯文本模式,关掉图形界面(不重启的情况)

    systemctl isolate graphical.target  #将目前的操作环境改为图形界面(不重启的情况)

    systemctl poweroff  #系统关机

    systemctl reboot   #重新开机

    systemctl suspend   #进入暂停模式

    systemctl rescue   #强制进入救援模式

    systemctl hibernate   #进入休眠模式

    systemctl emergency   #强制进入紧急救援模式

    systemctl list-dependencies --reverse   #查询当前默认的target关联了啥

    systemctl list-dependencies graphical.target  #查询图形界面模式的target关联了啥

    systemctl list-sockets   #查看当前的socket服务

    systemctl show etcd.service   #查看 unit 的详细配置情况

    systemctl mask etcd.service   #禁用某个服务

systemctl unmask etcd.service   #解除禁用某个服务

systemctl start network.service   #启动网络服务

systemctl stop network.service  #停止网络服务

systemctl restart network.service  #重启网络服务

systemctl status network.serivce  #查看网络服务状态

systemctl disable network.service  #禁止网络服务开机启动

systemctl enable network.service  #重新设置网络服务开机启动

systemctl is-active network.service  #查看网络服务是否启动

systemctl is-enabled network.service  #检查网络服务是否设置为开机启动

bootctl:用于查看和管理系统启动分区

hostnamectl:用于查看和修改系统的主机名和主机信息

journalctl:用于查看系统日志和各类应用服务日志

localectl:用于查看和管理系统的地区信息

loginctl:用于管理系统已登录用户和 Session 的信息

machinectl:用于操作 Systemd 容器

timedatectl:用于查看和管理系统的时间和时区信息

systemd-analyze 显示此次系统启动时运行每个服务所消耗的时间,可以用于分析系统启动过程中的性能瓶颈

systemd-ask-password:辅助性工具,用星号屏蔽用户的任意输入,然后返回实际输入的内容

systemd-cat:用于将其他命令的输出重定向到系统日志

systemd-cgls:递归地显示指定 CGroup 的继承链

systemd-cgtop:显示系统当前最耗资源的 CGroup 单元

systemd-escape:辅助性工具,用于去除指定字符串中不能作为 Unit 文件名的字符

systemd-hwdb:Systemd 的内部工具,用于更新硬件数据库

systemd-delta:对比当前系统配置与默认系统配置的差异

systemd-detect-virt:显示主机的虚拟化类型

systemd-inhibit:用于强制延迟或禁止系统的关闭、睡眠和待机事件

systemd-machine-id-setup:Systemd 的内部工具,用于给 Systemd 容器生成 ID

systemd-notify:Systemd 的内部工具,用于通知服务的状态变化

systemd-nspawn:用于创建 Systemd 容器

systemd-path:Systemd 的内部工具,用于显示系统上下文中的各种路径配置

systemd-run:用于将任意指定的命令包装成一个临时的后台服务运行

systemd-stdio- bridge:Systemd 的内部 工具,用于将程序的标准输入输出重定向到系统总线

systemd-tmpfiles:Systemd 的内部工具,用于创建和管理临时文件目录

systemd-tty-ask-password-agent:用于响应后台服务进程发出的输入密码请求

 

暂停模式与休眠模式的区别:

suspend:暂停模式会将系统的状态保存到内存中,然后关闭掉大部分的系统硬件,当然,并没有实际关机。当用户按下唤醒机器的按钮,系统数据会从内存中回复,然后重新驱动被大部分关闭的硬件,所以唤醒系统的速度比较快。

hibernate:休眠模式则是将系统状态保存到硬盘当中,保存完毕后,将计算机关机。当用户尝试唤醒系统时,系统会开始正常运行,然后将保存在硬盘中的系统状态恢复回来。因为数据需要从硬盘读取,因此唤醒的速度比较慢(如果你使用的是 SSD 磁盘,唤醒的速度也是非常快的)。

 

切换系统模式(文本、界面模式等)

这里我想特别提一下跟操作界面比较有关的target项目,毕竟常用的模式target有以下几种:

    graphical.target:就是文字加上图形界面,这个项目已经包含了下面的multi-user.target项目;

    multi-user.target:纯文本模式;

    rescue.target:在无法使用root登陆的情况下,systemd在开机时会多加一个额外的暂时系统,与你原本的系统无关。这时你可以取得root的权限来维护你的系统。但是这是额外系统,因此可能需要动到chroot的方式来取得你原有的系统;

    emergency.target:紧急处理系统的错误,还是需要使用root登陆的情况,在无法使用rescue.target时,可以尝试使用这种模式;

    shutdown.target:就是关机的流程;

getty.target:可以设置你需要几个tty之类的,如果想要降低tty的项目,可以修改这个东西的配置文件;

SysV-init level

systemctl target

Note

0

runlevel0.targatàshutdown.target/poweroff.target

关闭系统

1

runlevel1.targetàrescure.target

单用户模式

2

runlevel2.targetàmulti-user.target

用户定义/域特定运行级别,默认等同于级别3

3

runlevel3.targetàmulti-user.target

多用户模式

4

runlevel4.targetàmulti-user.target

用户定义/域特定运行级别,默认等同于级别3

5

runlevel5.targetàgraphical.target

多用户、图形模式

6

runlevel6.targetàreboot.target

重启

emergency

emergency.target

急救模式

通过systemctl list-units --type=target命令可以获取当前正在使用的运行目标。

正常的模式是 multi-user.target 和 graphical.target 两个,救援方面的模式主要是 rescue.target 以及更严重的 emergency.target。如果要修改可提供登陆的 tty 数量,则修改 getty.target。

服务的生命周期

当一个新的 Unit 文件被放入 /etc/systemd/system/ 或 /usr/lib/systemd/system/ 目录中时,它是不会被自识识别的。

1、服务的激活

systemctl enable:在 /etc/systemd/system/ 建立服务的符号链接,指向 /usr/lib/systemd/system/ 中

systemctl start:依次启动定义在 Unit 文件中的 ExecStartPre、ExecStart 和 ExecStartPost 命令

2、服务的启动和停止

systemctl start:依次启动定义在 Unit 文件中的 ExecStartPre、ExecStart 和 ExecStartPost 命令

systemctl stop:依次停止定义在 Unit 文件中的 ExecStopPre、ExecStop 和 ExecStopPost 命令

systemctl restart:重启服务

systemctl kill:立即杀死服务

3、服务的开机启动和取消

systemctl enable:除了激活服务以外,也可以置服务为开机启动

systemctl disable:取消服务的开机启动

4、服务的修改和移除

systemctl daemon-reload:Systemd 会将 Unit 文件的内容写到缓存中,因此当 Unit 文件被更新时,需要告诉 Systemd 重新读取所有的 Unit 文件

systemctl reset-failed:移除标记为丢失的 Unit 文件。在删除 Unit 文件后,由于缓存的关系,即使通过 daemon-reload 更新了缓存,在 list-units 中依然会显示标记为 not-found 的 Unit。

Target 管理

Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。

在传统的 SysV-init 启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似。不同的是,RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。

# 查看当前系统的所有 Target

$ systemctl list-unit-files --type=target

# 查看一个 Target 包含的所有 Unit

$ systemctl list-dependencies multi-user.target

# 查看启动时的默认 Target

$ systemctl get-default

# 设置启动时的默认 Target

$ sudo systemctl set-default multi-user.target

# 切换 Target 时,默认不关闭前一个 Target 启动的进程,systemctl isolate 命令改变这种行为,关闭前一个 Target 里面所有不属于后一个 Target 的进程

$ sudo systemctl isolate multi-user.target

 

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

日志管理

Systemd 通过其标准日志服务 Journald 提供的配套程序 journalctl 将其管理的所有后台进程打印到 std:out(即控制台)的输出重定向到了日志文件。

Systemd 的日志文件是二进制格式的,必须使用 Journald 提供的 journalctl 来查看,默认不带任何参数时会输出系统和所有后台进程的混合日志。

默认日志最大限制为所在文件系统容量的 10%,可以修改 /etc/systemd/journald.conf 中的 SystemMaxUse 来指定该最大限制。

# 查看所有日志(默认情况下 ,只保存本次启动的日志)

$ sudo journalctl

 

# 查看内核日志(不显示应用日志):--dmesg 或 -k

$ sudo journalctl -k

 

# 查看系统本次启动的日志(其中包括了内核日志和各类系统服务的控制台输出):--system 或 -b

$ sudo journalctl -b

$ sudo journalctl -b -0

 

# 查看上一次启动的日志(需更改设置)

$ sudo journalctl -b -1

 

# 查看指定服务的日志:--unit 或 -u

$ sudo journalctl -u docker.servcie

 

# 查看指定服务的日志

$ sudo journalctl /usr/lib/systemd/systemd

 

# 实时滚动显示最新日志

$ sudo journalctl -f

 

# 查看指定时间的日志

$ sudo journalctl --since="2012-10-30 18:17:16"

$ sudo journalctl --since "20 min ago"

$ sudo journalctl --since yesterday

$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"

$ sudo journalctl --since 09:00 --until "1 hour ago"

 

# 显示尾部的最新 10 行日志:--lines 或 -n

$ sudo journalctl -n

 

# 显示尾部指定行数的日志

$ sudo journalctl -n 20

 

# 将最新的日志显示在前面

$ sudo journalctl -r -u docker.service

 

# 改变输出的格式:--output 或 -o

$ sudo journalctl -r -u docker.service -o json-pretty

 

# 查看指定进程的日志

$ sudo journalctl _PID=1

 

# 查看某个路径的脚本的日志

$ sudo journalctl /usr/bin/bash

 

# 查看指定用户的日志

$ sudo journalctl _UID=33 --since today

 

# 查看某个 Unit 的日志

$ sudo journalctl -u nginx.service

$ sudo journalctl -u nginx.service --since today

 

# 实时滚动显示某个 Unit 的最新日志

$ sudo journalctl -u nginx.service -f

 

# 合并显示多个 Unit 的日志

$ journalctl -u nginx.service -u php-fpm.service --since today

 

# 查看指定优先级(及其以上级别)的日志,共有 8 级

# 0: emerg

# 1: alert

# 2: crit

# 3: err

# 4: warning

# 5: notice

# 6: info

# 7: debug

$ sudo journalctl -p err -b

 

# 日志默认分页输出,--no-pager 改为正常的标准输出

$ sudo journalctl --no-pager

 

# 以 JSON 格式(单行)输出

$ sudo journalctl -b -u nginx.service -o json

 

# 以 JSON 格式(多行)输出,可读性更好

$ sudo journalctl -b -u nginx.serviceqq

 -o json-pretty

 

# 显示日志占据的硬盘空间

$ sudo journalctl --disk-usage

 

# 指定日志文件占据的最大空间

$ sudo journalctl --vacuum-size=1G

 

# 指定日志文件保存多久

$ sudo journalctl --vacuum-time=1years

 

示例:

1、查看 unit 的配置

使用 show 子命令可以查看 unit 的详细配置情况:

[root@desktop ~]# systemctl show etcd.service

或者 systemctl cat etcd.service

Restart=no

NotifyAccess=none

RestartUSec=100ms

TimeoutStartUSec=1min 30s

TimeoutStopUSec=1min 30s

TimeoutAbortUSec=1min 30s

RuntimeMaxUSec=infinity

WatchdogUSec=0

WatchdogTimestampMonotonic=0

RootDirectoryStartOnly=no

2、注销与反注销 unit

如果我们想暂时的禁用某个 unit,比如 firewalld.service,可以注销这个 unit,注销之后就无法再启动这个服务了:

[root@desktop ~]# systemctl mask firewalld.service

Created symlink /etc/systemd/system/firewalld.service → /dev/null.

从上述中的输出我们可以看到,所谓的注销就是把 firewalld.service 文件链接到 /dev/null 这个空设备中去了。所以就无法再启动该服务了。下面我们尝试执行一次反注销:

[root@desktop ~]# systemctl unmask firewalld.service

Removed /etc/systemd/system/firewalld.service.

unmask 操作就是删除掉 mask 操作中创建的链接。

3、查看系统上的 unit

systemctl 提供了子命令可以查看系统上的 unit,命令格式为:

systemctl [command] [--type=TYPE] [--all]

command 有:

list-units:列出当前已经启动的 unit,如果添加 -all 选项会同时列出没有启动的 unit。

list-unit-files:根据 /lib/systemd/system/ 目录内的文件列出所有的 unit。

--type=TYPE:可以过滤某个类型的 unit。

不带任何参数执行 systemctl 命令会列出所有已启动的 unit:

# 列出正在运行的 Unit

$ systemctl list-units

 

# 列出所有Unit,包括没有找到配置文件的或者启动失败的

$ systemctl list-units --all

 

# 列出所有没有运行的 Unit

$ systemctl list-units --all --state=inactive

 

# 列出所有加载失败的 Unit

$ systemctl list-units --failed

 

# 列出所有正在运行的、类型为 service 的 Unit

$ systemctl list-units --type=service

 

# 查看 Unit 配置文件的内容

$ systemctl cat docker.service

 

# 显示远程主机的某个 Unit 的状态

$ systemctl -H root@rhel7.example.com status httpd.service

4、列举已经启动的unit

systemctl list-units (或者直接 sudo systemctl)

系统默认启动的服务是非常多的,上图只截取了前面几行。下面是对输出的介绍:

UNIT:项目的名称,包括各个 unit 的类别(看扩展名)。

LOAD:开机时 unit 的配置是否被加载。

ACTIVE:目前的状态,须与后续的 SUB 搭配!就是我们用 systemctl status 观察时,active的内容。

DESCRIPTION:描述信息。

注意,systemctl 不加参数,其实等同于 systemctl list-units

5、查看系统上一共装了多个unit

[root@desktop ~]# systemctl list-unit-files

UNIT FILE                                  STATE         

proc-sys-fs-binfmt_misc.automount          static        

-.mount                                    generated     

boot.mount                                 generated     

dev-hugepages.mount                        static        

dev-mqueue.mount                           static        

proc-fs-nfsd.mount                         static        

proc-sys-fs-binfmt_misc.mount              static        

sys-fs-fuse-connections.mount              static        

sys-kernel-config.mount                    static        

sys-kernel-debug.mount                     static        

tmp.mount                                  disabled      

var-lib-nfs-rpc_pipefs.mount               static        

systemd-ask-password-console.path          static        

systemd-ask-password-plymouth.path         static        

systemd-ask-password-wall.path             static        

session-2.scope                            transient     

session-4.scope                            transient     

accounts-daemon.service                    enabled

结果也非常的多,我们仍然只截取一部分结果。这里的 STATE 就是我们前面介绍的 服务的启动状态,有 enable 和 disable、static 和 mask。

  • enabled:已建立启动链接
  • disabled:没建立启动链接
  • static:该配置文件没有 [Install] 部分(无法执行),只能作为其他配置文件的依赖
  • masked:该配置文件被禁止建立启动链接

6、只查看某种类型的unit

比如我们只查看服务类型的unit:

[root@desktop ~]# systemctl list-units --type=service -all

  UNIT                                   LOAD      ACTIVE     SUB     JOB   DESCRIPTION                                                                 

  accounts-daemon.service                loaded    active     running       Accounts Service                                                             

  atd.service                            loaded    active     running       Deferred execution scheduler                                                

  auditd.service                         loaded    activating start   start Security Auditing Service                                                   

  auth-rpcgss-module.service             loaded    inactive   dead          Kernel Module supporting RPCSEC_GSS                                          

● autofs.service                         not-found inactive   dead          autofs.service                                                              

  chronyd.service                        loaded    active     running       NTP client/server                                                            

  cockpit-motd.service                   loaded    inactive   dead          Cockpit motd updater service                                                

  cockpit.service                        loaded    inactive   dead          Cockpit Web Service

7、查看加载失败的 unit

如果发现某个 unit 不工作,可以查看是否有 unit 加载失败:

[root@desktop ~]# systemctl --failed

  UNIT                           LOAD   ACTIVE SUB    DESCRIPTION                           

● kdump.service                  loaded failed failed Crash recovery kernel arming          

● kylin-activation-check.service loaded failed failed run kylin_activation_check at boot time

● kysec-sync-notify.service      loaded failed failed Kysec label sync daemon               

● lm_sensors.service             loaded failed failed Hardware Monitoring Sensors           

LOAD   = Reflects whether the unit definition was properly loaded.

ACTIVE = The high-level unit activation state, i.e. generalization of SUB.

SUB    = The low-level unit activation state, values depend on unit type.

4 loaded units listed.

8、检查 unit 之间的依赖性

很多服务之间是有依赖关系的,systemd 的一大亮点就是可以管理 unit 之间的依赖关系。我们可以通过下面的命令来查看 unit 间的依赖关系:

systemctl list-dependencies [unit] [--reverse]  #选项 --reverse 会反向追踪是谁在使用这个 unit。

 

下面让我们看看当前运行的 target 的依赖关系:

[root@desktop ~]# systemctl list-sockets

LISTEN                                 UNIT                            ACTIVATES

/dev/rfkill                            systemd-rfkill.socket           systemd-rfkill.service

/run/dbus/system_bus_socket            dbus.socket                     dbus.service

/run/dmeventd-client                   dm-event.socket                 dm-event.service

/run/dmeventd-server                   dm-event.socket                 dm-event.service

/run/initctl                           systemd-initctl.socket          systemd-initctl.service

/run/lvm/lvmetad.socket                lvm2-lvmetad.socket             lvm2-lvmetad.service

/run/lvm/lvmpolld.socket               lvm2-lvmpolld.socket            lvm2-lvmpolld.service

/run/rpcbind.sock                      rpcbind.socket                  rpcbind.service

/run/spice-vdagentd/spice-vdagent-sock spice-vdagentd.socket           spice-vdagentd.service

/run/systemd/coredump                  systemd-coredump.socket       

/run/systemd/journal/dev-log           systemd-journald-dev-log.socket systemd-journald.service

/run/systemd/journal/socket            systemd-journald.socket         systemd-journald.service

/run/systemd/journal/stdout            systemd-journald.socket         systemd-journald.service

/run/udev/control                      systemd-udevd-control.socket    systemd-udevd.service

[::]:9090                              cockpit.socket                  cockpit.service

audit 1                                systemd-journald-audit.socket   systemd-journald.service

kobject-uevent 1                       systemd-udevd-kernel.socket     systemd-udevd.service

route 1361                             systemd-networkd.socket         systemd-networkd.service

 

18 sockets listed.

Pass --all to see loaded but inactive sockets, too.

 

我们当前运行在 graphical.target 下,它由一个长长的依赖列表(上图并未展示所有的项目),其中最重要的依赖项目为 multi-user.target。下面我们使用 --reverse 选项查看 multi-user.target unit 被谁使用:

[root@desktop ~]# systemctl list-dependencies multi-user.target --reverse

multi-user.target

● └─graphical.target

[root@desktop ~]# systemctl get-default

graphical.target

从上面两条命令的执行结果上我们可以确定下面的关系:graphical.target 依赖 multi-user.target。

我们这里只是通过 target unit 介绍了如何查看 unit 之间的依赖关系,实际使用中更多的是检查服务 unit 之间的依赖关系。

9、systemctl daemon-reload 子命令

daemon-reload 是一个很容易被误用的子命令,主要是因为它名字中包含的 daemon 一词很容易让它和 reload 子命令混淆。

我们在前文简略的介绍了 reload 子命令,它的作用是重新加载某个服务程序的配置文件。这里的程序指的是服务类型 unit 的配置中指定的程序,也就是我们常说的 daemon(提供某种服务的应用程序)。比如服务类型的 unit prometheus.service,提供服务的 daemon 程序在我的机器上是 /usr/local/share/prometheus/prometheus,所以 reload 子命令重新加载的是 prometheus 的配置文件。

如果把 daemon-reload 子命令中的 daemon 理解为 systemd 程序,就可以把这个命令解释为重新加载 systemd 程序的配置文件。而所有的 unit 配置文件都是作为 systemd 程序的配置文件存在的。这样得出的结论就是:

新添加 unit 配置文件时需要执行 daemon-reload 子命令

有 unit 的配置文件发生变化时也需要执行 daemon-reload 子命令

daemon-reload 命令会做很多的事情,其中之一是重新生成依赖树(也就是 unit 之间的依赖关系),所以当你修改了 unit 配置文件中的依赖关系后如果不执行 daemon-reload 命令是不会生效的。

10.检查systemd和systemctl的二进制文件和库的安装位置。

# whereis systemd

systemd: /usr/lib/systemd /etc/systemd /usr/share/systemd /usr/share/man/man1/systemd.1.gz

# whereis systemctl

systemctl: /usr/bin/systemctl /usr/share/man/man1/systemctl.1.gz

11.检查systemd是否正在运行。

# ps -eaf | grep [s]ystemd

root         1     0  0 16:27 ?        00:00:00 /usr/lib/systemd/systemd --switched-root --system --deserialize 23

root       444     1  0 16:27 ?        00:00:00 /usr/lib/systemd/systemd-journald

root       469     1  0 16:27 ?        00:00:00 /usr/lib/systemd/systemd-udevd

root       555     1  0 16:27 ?        00:00:00 /usr/lib/systemd/systemd-logind

dbus       556     1  0 16:27 ?        00:00:00 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

注意:systemd作为父守护进程运行(PID = 1)。 在上面的命令ps中使用(-e)选择所有进程,( - a)选择除会话前导之外的所有进程和(-f)选择完整格式列表(即-eaf)。

另请注意上面示例中的方括号以及其他示例。 Square Bracket表达式是grep的字符类模式匹配的一部分。

12.分析systemd启动过程

# systemd-analyze

Startup finished in 1.487s (kernel) + 3.196s (initrd) + 3min 5.930s (userspace) = 3min 10.614s

graphical.target reached after 5.831s in userspace

13.分析每个进程在引导时花费的时间

打印所有运行单元,按它们初始化的时间排序。此信息可用于优化启动时间。注意,输出可能具有误导性,因为一个服务的初始化可能非常缓慢,因为它等待另一个服务的初始化完成

 

# systemd-analyze blame

8.565s mariadb.service

7.991s webmin.service

6.095s postfix.service

4.311s httpd.service

3.926s firewalld.service

3.780s kdump.service

3.238s tuned.service

1.712s network.service

1.394s lvm2-monitor.service

1.126s systemd-logind.service

....

14.分析启动时的关键链

# systemd-analyze critical-chain

The time when unit became active or started is printed after the "@" character.

The time the unit took to start is printed after the "+" character.

 

graphical.target @5.831s

└─network.service @2min 18.043s +1.117s

  └─vmware-tools.service @1.995s +2.029s

    └─basic.target @1.719s

      └─sockets.target @1.719s

        └─cockpit.socket @1.693s +25ms

          └─sysinit.target @1.691s

            └─systemd-update-utmp.service @1.681s +9ms

              └─auditd.service @1.680s

                └─systemd-tmpfiles-setup.service @1.570s +23ms

                  └─local-fs.target @1.567s

                    └─run-media-root-Kylin\x2dServer\x2d10.mount @1min 16.009s

                      └─local-fs-pre.target @1.319s

                        └─lvm2-monitor.service @206ms +1.112s

                          └─lvm2-lvmetad.service @287ms

                            └─lvm2-lvmetad.socket @196ms

                              └─system.slice

                                └─-.slice

重要:Systemctl接受服务(.service),挂载点(.mount),套接字(.socket)和设备(.device)作为单位。

15.systemd-run

systemd-run 可以将一个指定的操作变成后台运行的服务。它的效果似乎与直接在命令后加上表示后台运行的 & 符号很相似。然而,它让命令成为服务还意味着,它的生命周期将由 Systemd 控制。具体来说,包括以下好处:

服务的生命击期由 Systemd 接管,不会随着启动它的控制台关闭而结束

可以通过 systemctl 工具管理服务的状态

可以通过 journalctl 工具查看和管理服务的日志信息

可以通过 Systemd 提供的方法限制服务的 CPU、内存、磁盘 IO 等系统资源的使用情况。

Linux守护进程与初始化进程

1. 什么是守护进程

Linux服务器的主要任务就是为本地或远程用户提供各种服务。通常Linux系统上提供服务的程序是由运行在后台的守护进程(Daemon)来执行。一个实际运行中的Linux系统一般会有多个这样的程序在运行。这些后台守护进程在系统开机后就运行了,并且在时刻地监听前台客户地服务请求,一旦客户发出了服务请求,守护进程便为它们提供服务。Windows系统中的守护进程被称为“服务”。

按照服务类型,守护进程可以分为如下两类:

系统守护进程:如crond(周期任务)、rsyslogd(日志服务)、cpus等;

网络守护进程:如sshd、httpd、xinetd(托管)等。

2. 什么是守护进程

系统初始化进程是一个特殊的的守护进程,其PID为1,它是所有其他守护进程的父进程或者祖先进程。也就是说,系统上所有的守护进程都是由系统初始化进程进行管理的(如启动、停止等)。

在Linux的发展历史过程中,使用过3种Linux初始化系统。

SysVinit

为 UNIX System V 系统创建的;

RHEL/CentOS 5及之前的版本一直使用。

Upstart

由Ubuntu创建的;

RHEL/CentOS 6 使用Upstart。

Systemd

先进的初始化系统;

RHEL/CentOS 7使用Systemd。

Linux独立启动和超级守护进程

如果用两个比喻来形容两类守护进程的话,一般会用银行的业务处理窗口来类比:

独立启动守护进程:银行里有一种单服务的窗口,像取钱,存钱等窗口,这些窗口边上始终会坐着一个人,如果有人来取钱或存钱,可以直接到相应的窗口去办理,这个处理单一服务的始终存在的人就是独立启动的守护进程。

超级守护进程:银行里还有一种窗口,提供综合服务,像汇款,转账,提款等业务;这种窗口附近也始终坐着一个人(xinet),她可能不提供具体的服务,提供具体服务的人在里面闲着聊天啊,喝茶啊,但是当有人来汇款时他会大声喊一句,小王,有人汇款啦,然后里面管汇款的小王会立马跑过来帮忙办完汇款业务。其他的人继续聊天,喝茶。这些负责具体业务的人我们就称之为超级守护进程。当然可能汇款人会有一些规则,可能不能往北京汇款,他就会提早告诉xinet,所以如果有人来汇款想汇往北京的话,管理员就直接告诉他这个我们这里办不到的,于是就根本不会去喊汇款员了,相当于提供了一层管理机制。

 

针对这种窗口还存在多线程和单线程的区别:

多线程:将所有用户的要求都提上来,里面的人都别闲着了,都一起干活吧;

单线程:大家都排好队了,一个一个来,里面的人同一时间只有一个人在工作。

Linux守护进程运行方式

1. 独立运行(stand-alone)的守护进程

独立运行的守护进程由init脚本负责管理,所有独立运行的守护进程的脚本在/etc/rc.d/init.d/目录下。系统服务都是独立运行的守护进程,包括syslogd和cron等。独立运行的守护进程的工作方式称做stand-alone,它是UNIX传统的C/S模式的访问模式。

b1558e98c73c42d287ebc1791896b1b9.png

2.xinetd模式运行独立的守护进程

从守护进程的概念可以看出,对于系统所要通过的每一种服务,都必须运行一个监听某个端口连接所发生的守护进程,这意味着资源浪费。为了解决这个问题,Linux引进了"网络守护进程服务程序"的概念。也就是xinted(extended internet daemon)。xinetd能够同时监听多个指定的端口,在接受用户请求时,它能够根据用户请求的端口的不同,启动不同的网络服务进程来处理这些用户请求。可以把xinetd看做一个管理启动服务的管理服务器,它决定把一个客户请求交给哪个程序处理,然后启动相应的守护进程。xinetd无时不在运行并监听它所管理的所有端口上的服务。当某个要连接它管理的某项服务的请求到达时,xinetd就会为该服务启动合适的服务器。

e3a305e634aa4856be853ddb4364983f.png

 

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Ubuntu 20.04中安装systemctl可以通过以下步骤完成: 1. 首先,确保您的系统满足安装systemctl的要求。可以参考引用中的文章了解安装Ubuntu 20.04的要求和步骤。 2. 确认您已经以root用户身份登录到Ubuntu 20.04系统。 3. 打开终端并输入以下命令来安装systemctl: ```shell sudo apt-get install systemd ``` 这将安装systemd软件包,其中包含systemctl命令。 4. 安装完成后,您可以使用以下命令来验证systemctl是否成功安装: ```shell systemctl --version ``` 如果成功安装,您将看到systemctl的版本号。 请注意,systemctl是用于管理systemd服务的工具,它在Ubuntu 20.04及其他Linux发行版中是默认安装的。但是,如果您的系统不满足安装systemctl的要求,可能会导致安装过程中出现问题。因此,建议您在安装systemctl之前确保系统满足要求。引用中的文章提供了有关安装Ubuntu 20.04的要求和步骤的详细信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Ubuntu 20.04系统安装及初始配置](https://blog.csdn.net/weixin_46417939/article/details/128269012)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Ubuntu20.04安装Slurm21.08.6(实践篇)](https://blog.csdn.net/r1141207831/article/details/125272108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太极淘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值