Linux学习60 centos7新特性-systemd及systemctl实战

一、回顾

  1、CentOS系列系统启动流程

    POST --> Boot Sequeue(BIOS) --> Bootloader(MBR) --> Kernel(ramdisk) --> rootfs --> /sbin/init

  2、init:

    CentOS 5:SysV init(贝尔实验室的unix)

    CentOS 6:Upstart

    CentOS 7:Systemd

二、Systemd的新特性

  1、系统引导时实现服务并行启动

  2、按需激活进程

  3、系统状态快照

  4、基于依赖关系定义的服务控制逻辑

三、Systemd

  1、核心概念:unit(单元)

    a、unit由其相关配置文件进行标识、识别、配置;文件中主要包含了系统服务,监听的socket,保存的快照以及其它与init相关的信息;这些配置文件主要保存在

      (1)、/usr/lib/systemd/system

      (2)、/run/systemd/system

      (3)、/etc/systemd/system

          设定默认运行级别以及每一个级别下启动的服务和服务之间的依赖关系的

      (4)、这些路径下面有许许多多的文件,每一个文件我们都称其为一个unit文件,而这些unit文件是有类别的,以后缀名大体上可以做出分类来

        1)、以service结尾的是服务类unit

        2)、以target结尾的叫做目标类unit,什么叫目标类呢?他其实是用来模仿CentOS 6上运行级别的一种机制,这种称之为target类的unit

        3)、还有Socket,mount等

  2、unit的常见类型

    a、Service unit:文件扩展名为.service,用于定义系统服务,我们systemctl启动一个服务时主要就是靠此文件;

    b、Target unit:文件扩展名为.target,用于模拟实现"运行级别";

    c、Device unit:文件扩展名为.device,用于定义内核识别的设备,我们此前说过我们CentOS6上/dev目录下的这些设备文件是由udev根据/sys这个目录下由内核所探测然后输出的信息创建的。到了CentOS 7后systemd也能完成这个功能,因此我们CentOS7上相应的设备文件是由systemd和udev联合创建的,主要由systemd完成,而systemd主要是用来识别硬件的就是靠这个Device unit配置文件来实现的。

    d、Mount unit:.mount,定义文件系统挂载点事实上我们CentOS7以后,也就是我们linux内核3.0以后大量使用了cgroup(控制组)来实现资源分配了。对于我们CentOS7来讲我们输入mount即可看到,他主要是实现资源分配的内核中的一种资源分配机制。我们的docker技术主要就依赖于内核中的cgroup机制和namespace机制来实现。因此systemd还要负责激活这些控制组并且实现资源分配,那么他们如何实现挂载并且挂载点的创建systemd也会进行参与。

    e、Socket unit:.socket,套接字unit文件,用来标识进程间通信用的socket文件的。我们说过某一个服务启动并监听在某套接字上时就需要先创建一个套接字文件,而这些可以由socket unit来负责管理。因此他是用于标识进程间通信用到的socket文件,因此任何进程监听在一个套接字上或者任何进程打开一个随机的端口去与别的服务器上的进程通信时都需要创建socket文件。现在这些创建功能是由systemd负责管理实现的

    f、Snapshot unit:.snapshot,管理系统快照

    g、Swap unit: .swap,用于标识swap设备

    h、Automount unit:.automount,文件系统自动挂载点设置

    i、Path unit:.path,用于定义文件系统中的一个文件或目录;如果不存在systemd会自动创建。

  3、关键特性

    a、基于socket的激活机制:socket与程序分离,我们可以在启动某个服务时先把socket分配给它,但是进程可以先不启。

    b、基于bus的激活机制:即我们激活设备时可以基于总线激活,如果总线上存在对某一个服务的访问,那么我们就基于总线的这个请求将设备激活。

    c、基于device的激活机制:比如当某个设备插入的时候他会自动去激活mount unit,device unit以及automount unit,他能够监控我们当前系统上或我们内核中所输出的硬件信息,一旦发现某一个硬件来了就先给他创建设备文件,再给他自动挂载至某挂载点。挂载点不存在还能自动创建。

    d、基于Path的激活机制:我们系统会监控某个目录有没有,某个文件在不在,如果某个文件在的话他就立马能够激活另外一个服务,或者能激活另外一个进程。比如万一某个服务在运行中突然因为bug崩溃了他崩溃时创建了一个log文件或锁文件之类的,一旦我们systemd发现了这个锁文件他就立即去激活一个额外的程序去提供检测,比如激活一个窗口告诉你bug产生了,要不要发送报告之类的。

    e、系统快照:保存各unit的当前状态,因为systemd的所有管理功能都是通过各unit来实现的,因此他能保存各unit的当前状态信息于持久存储设备中,如果将来我们要回到这一刻,比如过了两小时发现某个地方出错了想回滚,他就可以提供回滚的功能,让你可以在过去到现在之间游走。

    f、向后兼容sysv init脚本,相当于放在/etc/init.d/下的脚本也一样可以通过systemd来启动控制。

  4、不兼容功能

    a、systemctl的命令是固定不变的,像此前的service脚本是我们自己编写的而支持start,restart,stop,status等,我们想新增一个也可以,脚本想怎么写就怎么写。而我们现在的所有脚本都是由systemctl来控制的,这个命令对每一个unit所支持的格式是固定的,是不可变的,不能加也不能减,除非我们自己去编写systemctl和systemd这个程序。

    b、非由systemd启动的服务,systemctl无法与之通信,也就无法控制此服务,不过必要的时候我们写一个unit脚本即可。

四、CentOS7管理系统服务

  1、CentOS 7:service类型的unit文件

  2、systemctl 命令

    systemctl - Control the systemd system and service manager

    systemctl [OPTIONS...] COMMAND [NAME...]

    a、服务操作

      (1)、启动服务:service NAME start ==> systemctl start NAME.service

      (2)、停止服务:service NAME stop ==> systemctl stop NAME.service

      (3)、重启服务:service NAME restart ==> systemctl restart NAME.service

      (4)、状态:service NAME status ==> systemctl status NAME.service

        状态显示是不一样的,对于CentOS7来讲status显示的结果

[root@www ~]# systemctl status httpd.service 
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:httpd(8)
           man:apachectl(8)

        loaded:表示我们这个httpd.service文件已经被load了,什么叫被load了呢?我们CentOS6上有个命令叫做chkconfig --add,这个过程称之为添加到服务列表中去的过程,而此处的Load就表示他的unit文件已经被systemd装载了,与他的启动与否无关,只是表示添加进来了。最后有个disabled这个关键词,就表示服务是禁用的。因此我们当前是关闭的,所以我们下面的Active中显示是dead。如果后面是enabled就表示下次开机启动就会激活,但是此处的激活并不是说服务就会启动起来,他会在第一次访问时才会启动。然后我们现在将服务启动起来再查看

[root@www ~]# systemctl start httpd.service 
[root@www ~]# systemctl status httpd.service 
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 二 2020-03-31 15:04:56 CST; 3s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 4122 (httpd)
   Status: "Processing requests..."
   Memory: 5.1M
   CGroup: /system.slice/httpd.service
           ├─4122 /usr/sbin/httpd -DFOREGROUND
           ├─4123 /usr/sbin/httpd -DFOREGROUND
           ├─4124 /usr/sbin/httpd -DFOREGROUND
           ├─4125 /usr/sbin/httpd -DFOREGROUND
           ├─4126 /usr/sbin/httpd -DFOREGROUND
           ├─4127 /usr/sbin/httpd -DFOREGROUND
           └─4128 /usr/sbin/httpd -DFOREGROUND

3月 31 15:04:19 www.wohaoshuai.com systemd[1]: Starting The Apache HTTP Server...
3月 31 15:04:34 www.wohaoshuai.com httpd[4122]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using www.wohaoshuai.com. Set the 'Serv...his message
3月 31 15:04:56 www.wohaoshuai.com systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.

        可以看到我们的服务已经启动起来了但是状态还是disabled的,因为我们并没有设置开机启动。

      (5)、条件式重启:即服务如果不存在就启动起来,如果存在的话就算了

        service NAME condrestart ==> systemctl try-restart NAME.service

      (6)、重载或重启服务:意思是我们要让某一个服务重载其配置文件时他如果支持重载就重载,不支持重载就重启

        systemctl reload-or-restart NAME.service

      (7)、重载或条件式重启服务

        systemctl reload-or-try-restart NAME.service

      (8)、查看某服务当前激活与否的状态

        systemctl is-active httpd.service

      (9)、查看所有已激活的服务

        systemctl list-units --type service

      (10)、查看所有服务(已激活及未激活)

        chkconfig --list ==> systemctl list-units -t service --all

      (11)、设置服务开机自启动

        chkconfig NAME on ==> systemctl enable NAME.service

      (12)、禁止服务开机自启动

        chkconfig NAME off ==> systemctl disable NAME.service

      (13)、查看某服务是否能开机自启动

        chkconfig --list NAME ==> systemctl is-enabled NAME.service

      (14)、禁止某服务设定为开机自启动

        systemctl mask NAME.service

        取消此禁止:

        systemctl unmask NAME.service

      (15)、查看服务的依赖关系

        systemctl list-dependencies NAME.service

    b、管理target units:用来模拟运行级别的

      (1)、运行级别:

        0 ==> runlevel0.target,poweroff.target

          CentOS7如果要关机可以使用systemd halt或systemd poweroff

        1 ==> runlevel1.target,rescue.target(救援模式),使用systemd 1就进入救援模式

        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

      (2)、级别切换

        init N ==> systemctl isolate NAME.target

      (3)、查看当前级别

        runlevel ==> systemctl list-units -t target

      (4)、查看所有的target,包括未激活的

        systemctl list-units -t target --all

      (5)、获取默认运行级别

        systemctl get-default

      (6)、修改默认运行级别

        systemctl set-default NAME.target

      (7)、切换至紧急救援模式:systemctl rescue,此模式也会执行系统初始化脚本rc.sysinit

      (8)、切换至emergency模式

        在centos6中我们切换至紧急救援模式后他还是会启动/etc/rc.d/rc.sysinit脚本,但是emergency模式不会。而rc.sysinit脚本他会有很多操作,比如设置主机名,激活udev,激活selinux激活swap,挂载fstab文件中定义的各种各样的文件系统一切都是由这个服务脚本来实现的。而对于emergency模式而言这个脚本是不会被执行的,因此很多驱动他就不会被加载。各种各样的系统初始化功能都不会被执行。因此这个模式才是最简洁的系统维护模式,只有我们因为装载了错误的系统驱动导致我们一旦装载驱动系统就崩溃的时候才会切换至此模式

        systemctl emergency

  3、其它常用命令

    a、关机

      systemctl halt ,systemctl poweroff

    b、重启

      systemctl reboot

    c、挂起

      systemctl suspend

    d、快照

      systemctl hibernate

    e、快照并挂起

      systemctl hybrid-sleep

  4、service unit file组织结构

    a、我们可以查看我们的httpd.service文件

[root@www ~]# cat /usr/lib/systemd/system/httpd.service 
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/httpd
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
ExecStop=/bin/kill -WINCH ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.
KillSignal=SIGCONT
PrivateTmp=true

[Install]
WantedBy=multi-user.target

    b、文件组成

      (1)、[Unit]:定义与Unit类型无关的通用选项,用于提供unit的描述信息,unit行为及依赖关系等

        1)、Description,描述

        2)、After,后面的服务只有启动起来才运行此服务

      (2)、[Service]:定义与特定类型相关的专用选项,此处为Service类型

      (3)、[Install]:定义由"systemctl enable"以及systemctl disable命令在实现服务启用或禁用时用到的一些选项

    c、Unit段的常用选项

      (1)、Description:描述信息;意义性描述

      (2)、After:定义unit的启动次序,表示当前unit应该晚于哪些unit启动,其功能与Before想反

      (3)、Requles:依赖到的其它units,强依赖,定义的相应的units必须要启动我们的服务才能启动

      (4)、Wants:依赖到的其它unit。弱依赖;即表示当前需要依赖定义的相应的unit,如果相应的unit没有激活我们的unit也能启动。

      (5)、Confilcts:定义units之间的冲突关系

    d、Service段的常用选项

      (1)、Type:用于定义影响ExecStart及相关参数的功能的unit进程启动类型

        1)、simple:默认就是simple,他表示由ExecStart启动的进程就是服务的主进程,我们服务启动起来后可以有主进程和许多子进程,比如httpd或者nginx都可以有很多主进程和许多子进程

        2)、forking:表示复制自身的一种操作,这表示由ExecStart指明了程序所启动的进程生成的一个子进程为主进程,他可能会生成很多子进程但是其中一个子进程是主进程,而且启动完成以后这个父进程会退出,因为已经选出了新的子进程为主进程了

        3)、oneshot:功能类似于simple,不过在启动后续的unit之前主进程会退出

        4)、dbus:也类似于simple但是后续的unit仅在主进程得到dbus名称之后才会启动

        5)、notify:类似于simple,但是他还有另外一个作用,他表示后续的unit仅在notify函数发送通知以后然后才能运行这个命令

        6)、idle:也类似于simple

      (2)、ExecStart:指明启动unit要运行命令或脚本ExecStartPre,ExecStartPost,即运行之前和运行之后的命令

      (3)、ExecStop:指明停止unit要运行的命令或脚本

      (4)、Restart:如果进程意外终止了他会自动把它运行起来

      (5)、EnvironmentFile:环境配置文件,此文件在ExecStart之前被读取并为ExecStart提供一些变量等自定义功能

    e、Install段的常用选项

      (1)、Alias:当前unit的别名

      (2)、RequiredBy:被哪些unit所依赖,强依赖

      (3)、WantedBy:被哪些units所依赖,弱依赖

  5、注意:对于新创建的unit文件或修改了的unit文件,要通知systemd重载此配置文件

    systemctl daemon-reload

  6、联习

    为当前系统的httpd服务提供一个unit文件