Linux systemd 基础及命令

From the project web page:

systemd is a suite of basic building blocks for a Linux system. It provides a system and service manager that runs as PID 1 and starts the rest of the system. systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, maintains mount and automount points, and implements an elaborate transactional dependency-based service control logic. systemd supports SysV and LSB init scripts and works as a replacement for sysvinit. Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution.

支持的主要单元:服务单元(.service),挂载单元(.mount),目标单元(.target)等

默认情况下,systemd会在启动单元的同时启动其所有的Requires和Wants依赖组件。
Requires和Wants定义依赖关系并没有设定顺序,使用顺序关键字(Before和After)来设定顺序
        Before:当前单元会在Before中列出的单元之前启动
        After: 当前单元在After中列出的单元之后启动

记住这个原则即可:
        不要更改系统单元目录,因为它由系统来维护。可以在系统配置目录中保存你的自定义设置。在选择更改/usr还是更改/etc时,永远选择/etc

# There are two safe ways to modify a unit without touching the original file: 
# create a new unit file which overrides the original unit or create drop-in snippets which are applied on top of the original unit.
# Replace or Drop-in unit files, with parameter --full is Replace mode, otherwise Drop-in mode
$ sudo systemctl edit [--full] ssh.service
	
# To revert any changes to a unit made using systemctl edit
$ systemctl revert ssh.service

默认情况下,systemctl edit使用nano作为编辑器,使用如下方法改变使用vi作为编辑器

$ vi ~/.bashrc
    export SYSTEMD_EDITOR=vim
$ sudo visudo
	Defaults  env_keep += "SYSTEMD_EDITOR"

Install节

sshd.service
[Unit]
Description=OpenSSH server daemon
After=syslog.target network.target auditd.service
	
[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
	
[Install]
WantedBy=multi-user.target

单元文件中的[Install]区块很重要,因为它告诉我们怎样使用systemd的WantedBy和RequiredBy依赖关系
    这部分配置的目标模块通常是特定运行目标的.target文件,用来使得服务在系统启动时自动运行。这个区段可以包含三种启动约束:
        WantedBy:和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。
            它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system目录下面以+.wants后缀构成的子目录中,如 "/etc/systemd/system/multi-user.target.wants/"
        RequiredBy:和 Unit 段的 Requires作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。
            它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入 /etc/systemd/system目录下面以+.required后缀构成的子目录中
        Also:当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
        Alias:当前 Unit 可用于启动的别名

Unit 模板文件的写法与普通的服务 Unit 文件基本相同,不过 Unit 模板的文件名是以 @ 符号结尾的。通过模板启动服务实例时,需要在其文件名的 @ 字符后面附加一个参数字符串。
    Systemd 在运行服务时,总是会先尝试找到一个完整匹配的 Unit 文件,如果没有找到,才会尝试选择匹配模板。

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

systemd启动流程

Linux systemd 基础及命令_第1张图片 

target配置流程(实际启动时从最底层的local-fs-pre.target开始执行)
      

 -> default.target (=graphical.target by default) 
        Requires=multi-user.target
        Wants=display-manager.service
        Conflicts=rescue.service rescue.target
        After=multi-user.target rescue.service rescue.target display-manager.service

            This tells systemd to start everything in the multi-user.target before starting the graphical target. 
            Once that's done, the "Wants" entry tells systemd to start the display-manager.service service (/etc/systemd/system/display-manager.service), which runs the GNOME display manager (/usr/sbin/gdm).
      

 -> multi-user.target
        Requires=basic.target
        Conflicts=rescue.service rescue.target
        After=basic.target rescue.service rescue.target

            This tells systemd to start everything in the /lib/systemd/system/basic.target target before starting the other multi-user services. 
            After that, for the multi-user.target, all units (services, targets, etc.) in the /etc/systemd/system/multi-user.target.wants and /lib/systemd/system/multi-user.target.wants directories are started. 
            When you enable a service, a symbolic link is placed in the /etc/systemd/system/multi-user.target.wants directory. 
            That directory is where you will find links to most of the services you think of as starting in multi-user mode (printing, cron, auditing, SSH, and so on).
      

 -> basic.target 
        Requires=sysinit.target
        Wants=sockets.target timers.target paths.target slices.target
        After=sysinit.target sockets.target paths.target slices.target tmp.mount

            This points systemd to the /lib/systemd/system/sysinit.target, which must start before the basic.target can continue. 
            The basic.target target file starts the firewalld and microcode services from the /etc/systemd/system/basic.target.wants directory and services for SELinux, kernel messages, and loading modules from the /lib/systemd/system/basic.target.wants directory.

-> sysinit.target 
        Conflicts=emergency.service emergency.target
        Wants=local-fs.target swap.target
        After=local-fs.target swap.target emergency.service emergency.target

            Besides mounting file systems and enabling swap devices, the sysinit.target starts targets, services, and mounts based on units contained in the /lib/systemd/system/sysinit.target.wants directory. 
            These units enable logging, set kernel options, start the udevd daemon to detect hardware, and allow file system decryption, among other things. 
The /etc/systemd/system/sysinit.target.wants directory contains services that start iSCSI, multipath, LVM monitoring and RAID services.

-> local-fs.target
        Conflicts=shutdown.target
        After=local-fs-pre.target

            There are no services associated with the local-fs-pre.target target (you could add some to a "wants" directory if you like). 
            However, units in the /lib/systemd/system/local-fs.target.wants directory import the network configuration from the initramfs, run a file system check (fsck) on the root file system when necessary, and remounting the root file system (and special kernel file systems) based on the contents of the /etc/fstab file.

启动时通过/etc/systemd/system/unit.target.wants目录来决定哪些服务会被当前target启动

systemctl service和target相关命令

# 获取当前正在使用的运行目标
# systemctl list-units --type=target
	
# 只重新加载unit单元的配置
$ systemctl reload unit:
# 重新加载所有的单元配置
$ systemctl daemon-reload:
	
# 显示单元的配置文件或配置参数
$ systemctl [cat|show] docker.service

# 显示单元的依赖关系
$ systemctl list-dependencies docker.service
	
# 查看当前系统的所有 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 的进程
# This will only change the current target, and has no effect on the next boot
$ sudo systemctl isolate multi-user.target

 journalctl命令

# 查看所有日志(默认情况下 ,只保存本次启动的日志)
$ 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

参考:

https://cloud.tencent.com/developer/article/1516125

https://wiki.archlinux.org/title/Systemd#Running_services_after_the_network_is_up

https://linux.cn/article-5457-1.html

https://access.redhat.com/articles/754933

你可能感兴趣的:(Linux,linux,systemd)