centos7 systemd 必知必会

systemd 简介:

systemd 是一个 Linux 系统基础组件的集合, 提供了一个系统和服务管理器, 运行为 PID 1 并负责启动其它程序
功能包括:
    1、支持并行化任务
    2、同时采用 socket 与 D-Bus 总线激活服务
    3、按需启动守护进程(daemon), 利用 Linux 的 cgroups 监视进程
    4、支持快照和系统恢复, 维护挂载点和自动挂载点, 各服务间基于依赖关系进行精密控制
    5、支持 SysV 和 LSB 初始脚本, 可以替代 sysvinit
    6、日志进程、控制基础系统配置, 维护登陆用户列表以及系统账户、运行时目录和设置
    7、运行容器和虚拟机, 可以简单的管理网络配置、网络时间同步、日志转发和名称解析等

  

systemd 和 init:

centos7 以前, centos 的启动一直采用 init 的启动方式
但是这种方式有两种缺点:
    1、启动时间长, init 是串行启动, 只有前一个进程启动完, 才会启动下一个进程
    2、启动脚本复杂, init 进程只是执行启动脚本, 不管其他事情, 脚本需要自己处理各种情况, 这往往使得脚本变得很长

systemd 就是为了解决 init 的问题而诞生的一种新型的启动方式
    1、systemd 按需启动服务, 尽量减少系统资源消耗
    2、尽可能并行启动进程, 减少系统启动等待时间

systemd 尽管解决了 init 所留下的问题, 但是其也产生了新的问题
    1、其最注意的问题之一就是体系庞大, 非常复杂。与操作系统的其他部分强耦合, 违反了 unix 的哲学 keep simple, keep stupid
    2、在 centos 目前的版本中, systemd 的 bug 较多

  

Unit 管理:

systemd 可以管理所有系统资源。不同的资源统称为 Unit
Unit 一共分成12种:
    Service unit    系统服务
    Target unit     启动组
    Device Unit     系统设备
    Mount Unit      挂载点
    Automount Unit  自动挂载点
    Path Unit       文件路径
    Scope Unit      不是由 Systemd 启动的外部进程
    Slice Unit      进程组
    Snapshot Unit   systemd 快照
    Socket Unit     进程间通信的 socket
    Swap Unit       交换分区
    Timer Unit      由 systemd 管理的计时器


Unit 管理命令:
    # 启动一个 Unit
    systemctl start UNIT_NAME
    
    # 停止一个 Unit
    systemctl stop UNIT_NAME

    # 杀死一个 Unit
    systemctl kill UNIT_NAME
    
    # 重启一个 Unit
    systemctl restart UNIT_NAME

    # 重新加载 Unit 配置文件
    systemctl reload UNIT_NAME

    # 查看 Unit 状态
    systemctl status UNIT_NAME

    # 检查 Unit 是否为开机自启动
    systemctl is-enabled UNIT_NAME

    # 检查 Unit 是否处于运行状态
    systemctl is-active UNIT_NAME

    # 检查 Unit 是否处于启动失败状态
    systemctl is-failed UNIT_NAME

    # 将 Unit 设置为开机自启动
    systemctl enable UNIT_NAME

    # 取消 Unit 的开机自启动
    systemctl disable UNIT_NAME

    # 禁用 Unit
    systemctl mask UNIT_NAME 

    # 取消禁用
    systemctl unmask UNIT_NAME

    # 查看 Unit 帮助信息(由 Unit 文件提供)
    systemctl help UNIT_NAME

    # 重新载入 systemd 系统配置, 扫描 Unit 文件的变动
    systemctl daemon-reload UNIT_NAME

    # 列出正在运行的 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

    # 显示系统状态
    systemctl status

    # 显示一个 Unit 的所有底层参数
    systemctl show UNIT_NAME

    # 显示一个 Unit 的指定属性的值
    systemctl show -p ATTR UNIT_NAME

    # 设置一个 Unit 的指定属性
    sudo systemctl set-property UNIT_NAME ATTR=VALUE

    # 列出一个 Unit 的所有依赖(--all 展开 target)
    systemctl list-dependencies --all UNIT_NAME

  

电源管理:

# 重启
systemctl reboot

# 关闭电源
systemctl poweroff

# 待机
systemctl suspend

# 休眠
systemctl hibernate

# 混合休眠模式(同时休眠到硬盘并待机)
systemctl hybrid-sleep

  

Unit 配置文件:

每一个 Unit 都有一个配置文件, 告诉 Systemd 怎么启动这个 Unit
systemd 默认从 /etc/systemd/system/ 读取配置文件
但是 /etc/systemd/system/ 里面存放的大部分文件都是符号链接, 指向 /usr/lib/systemd/system/ 真正的配置文件一般都存放在这个目录

systemctl enable 命令用于在上面两个目录之间, 建立符号链接关系
systemctl disable 命令用于在上面两个目录之间, 取消符号链接关系

默认情况下, Unit 配置文件的后缀应该等于 Unit 的种类, 比如 sshd.socket。如果省略 systemd 默认后缀名为 .service, 所以 sshd 会被理解成 sshd.service

# 列出所有配置文件
systemctl list-unit-files

# 列出指定类型的配置文件
systemctl list-unit-files --type=service


systemctl list-unit-files 命令会输出一个文件列表, 该列表有两列 UNIT FILE 和 STATE
UNIT FILE 为 配置文件的名称, STATE 为该 UNIT 的状态
STATE 一共有 4 种状态:
    enabled         已建立启动链接
    disabled        没有建立启动链接
    static          该配置文件没有 [Install] 部分(无法执行), 只能作为其他配置文件的依赖
    masked          该配置文件被禁止建立启动链接


配置文件格式:
    # 查看 sshd.service 的配置文件
    systemctl cat sshd 

    Unit 配置文件分为多个区块, 每个区块的第一行, 是用方括号表示的区块名(section), Unit 配置文件严格区分大小写
    
    Unit 配置文件区块字段:
        [Unit] 区块通常是配置文件的第一个区块, 用来定义 Unit 的元数据, 以及配置与其他 Unit 的关系, 它的主要字段如下:
            Description         简短描述
            Documentation       文档地址
            Requires            当前 Unit 依赖的其他 Unit, 如果它们没有运行, 当前 Unit 会启动失败
            Wants               与当前 Unit 配合的其他 Unit, 如果它们没有运行, 当前 Unit 不会启动失败
            BindsTo             与 Requires 类似, 它指定的 Unit 如果退出, 会导致当前 Unit 停止运行
            Before              如果该字段指定的 Unit 也要启动, 那么必须在当前 Unit 之后启动
            After               如果该字段指定的 Unit 也要启动, 那么必须在当前 Unit 之前启动
            Conflicts           这里指定的 Unit 不能与当前 Unit 同时运行
            Condition           当前 Unit 运行必须满足的条件, 否则不会运行
            Assert              当前 Unit 运行必须满足的条件, 否则会报启动失败

        [Install] 区块通常是配置文件的最后一个区块, 用来定义如何启动, 以及是否开机启动, 它的主要字段如下:
            WantedBy    它的值是一个或多个 Target, 当前 Unit 激活时(enable) 符号链接会放入 /etc/systemd/system/ 中以 Target 名 + .wants 构成的目录中
            RequiredBy  它的值是一个或多个 Target, 当前 Unit 激活时(enable) 符号链接会放入 /etc/systemd/system/ 中以 Target 名 + .required 构成的目录中
            Alias       当前 Unit 可用于启动的别名
            Also        当前 Unit 激活(enable) 时, 会被同时激活的其他 Unit

        [Service] 区块用来设置 Service 的配置, 只有 Service 类型的 Unit 才有这个区块, 它的主要字段如下:
            Type            定义启动时的进程行为。它有以下几种值。
                Type=simple         默认值, 执行 ExecStart 指定的命令, 启动主进程, 服务进程不会 fork。如果该服务要启动其他服务, 不要使用此类型启动
                Type=forking        以 fork 方式从父进程创建子进程, 创建后父进程会立即退出, 使用此类型启动时应指定 PIDFile= 以便 systemd 跟踪服务的主进程
                Type=oneshot        这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态
                Type=notify         与 Type=simple 相同,但服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供
                Type=dbus           使用 D-Bus 启动
                Type=idle           systemd 会等待所有任务处理完成后, 才开始执行 idle 类型的单元。其他行为与 Type=simple 类似

            ExecStart       启动当前服务的命令
            ExecStartPre    启动当前服务之前执行的命令
            ExecStartPost   启动当前服务之后执行的命令
            ExecReload      重启当前服务时执行的命令
            ExecStop        停止当前服务时执行的命令
            ExecStopPost    停止当其服务之后执行的命令
            RestartSec      自动重启当前服务间隔的秒数
            Restart         定义何种情况下 systemd 会尝试重启当前服务
                no              默认值, 不会尝试重启当前服务
                always          总是重启
                on-success      服务进程正常退出时才会重启(退出状态码为 0)
                on-failure      当服务进程以非 0 退出状态码退出时才会重启
                on-abnormal     当一个信号(包括核心转储,不包括SIGHUP, SIGINT, SIGTERM 或 SIGPIPE), 操作超时或触发看门狗超时终止进程时, 服务将重新启动
                on-abort        当服务进程因发送非指定的信号而退出时, 才会重新启动服务
                on-watchdog     当服务的看门狗进程超时时, 才会重新启动该服务

                # Restart 值的对应关系(参考: https://www.freedesktop.org/software/systemd/man/systemd.service.html)
                Restart settings/Exit causes	no	always	on-success	on-failure	on-abnormal	 on-abort  on-watchdog
                Clean exit code or signal	 	      X	        X	 	 	 	 
                Unclean exit code	 	              X	 	                X	 	 	 
                Unclean signal	 	                  X	 	                X	        X	        X	 
                Timeout	 	                          X	 	                X	        X	 	 
                Watchdog	 	                      X	 	                X	        X	 	                X

            TimeoutSec      定义 systemd 停止当前服务之前等待的秒数
            Environment     指定环境变量


    示例:(centos7 httpd)
        [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}
        KillSignal=SIGCONT
        PrivateTmp=true

        [Install]
        WantedBy=multi-user.target


    # 一旦修改配置文件, 就要让 systemd 重新加载配置文件, 然后重新启动, 否则修改不会生效
    systemctl daemon-reload
    systemctl restart UNIT_NAME

  

Target:

    运行级别(runlevel)是一个旧的概念, systemd 引入了一个和运行级别功能相似又不同的概念--目标(target)
    不像数字表示的启动级别, 每个目标都有名字和独特的功能, 并且能同时启用多个
    一些目标继承其他目标的服务, 并启动新服务。systemd 提供了一些模仿 sysvinit 运行级别的目标, 仍可以使用旧的 telinit 运行级别 命令切换

    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, 该命令仅更改当前运行目标, 对下次启动无影响
        $ sudo systemctl isolate multi-user.target

    SysV 运行级别" 与 "systemd target" 对照表
        SysV 运行级别	    Systemd target	                                                注释
            0	            runlevel0.target,  poweroff.target	                            中断系统
            1	            runlevel1.target,  rescue.target	                            单用户模式
            2, 4	        runlevel2.target,  runlevel4.target, multi-user.target	        用户自定义运行级别, 通常识别为级别3
            3	            runlevel3.target,  multi-user.target	                        多用户, 无图形界面。用户可以通过终端或网络登录
            5	            runlevel5.target,  graphical.target	                            多用户, 图形界面。继承级别3的服务, 并启动图形界面服务
            6	            runlevel6.target,  reboot.target	                            重启
            emergency	    emergency.target	                                            急救模式(Emergency shell)

    systemd 和 SysV 的区别:
    1、默认的 RunLevel 在 /etc/inittab 文件设置, 被默认的 Target 取代, 位置是 /etc/systemd/system/default.target
        通常符号链接到 graphical.target(图形界面) 或者 multi-user.target (多用户命令行)

    2、启动脚本的位置, 以前是 /etc/init.d 目录, 符号链接到不同的 RunLevel 目录 (比如/etc/rc3.d、/etc/rc5.d等)
        现在则存放在 /lib/systemd/system 和 /etc/systemd/system 目录

    3、配置文件的位置, 以前 init 进程的配置文件是 /etc/inittab, 各种服务的配置文件存放在 /etc/sysconfig 目录
        现在的配置文件主要存放在 /lib/systemd 目录, 在/etc/systemd目录里面的修改可以覆盖原始设置。

  

参考:
  http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
  https://wiki.archlinux.org/index.php/Systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

猜你喜欢

转载自www.cnblogs.com/huyuanblog/p/10078442.html