背景

在Linux操作系统中,系统会首先启动init daemon (pid = 1)做为第一个进程,其以守护进程的形式在系统中运行,直到系统关闭。守护进程一种在后台执行,而不由用户直接交互控制的程序。init daemon可以作为其他所有进程的父进程,来管理所有其他进程的启动。

Centos7之前,是通过Init架构(又被称为System V Init或SysVinit)来实现init daemonCentos6,而现在Centos系统一般都是以Systemd架构来实现init daemon。我们可以通过pstree -p命令来查看进程树。

yum -y install psmisc
pstree -p
[root@www ~]# pstree -p
systemd(1)─┬─NetworkManager(696)─┬─{NetworkManager}(714)
│ └─{NetworkManager}(716)
├─agetty(713)
├─atd(703)
├─auditd(665)───{auditd}(666)
├─crond(705)
├─dbus-daemon(691)
├─httpd(934)─┬─httpd(1476)
│ ├─httpd(1477)
│ ├─httpd(1478)
│ ├─httpd(1479)
│ └─httpd(1480)
├─irqbalance(689)
├─lvmetad(539)
├─master(1248)─┬─pickup(1279)
│ └─qmgr(1280)
├─mysqld_safe(1084)───mysqld(1291)─┬─{mysqld}(1457)
│ ├─{mysqld}(1458)
│ ├─{mysqld}(1459)
│ ├─{mysqld}(1460)
│ ├─{mysqld}(1461)
│ ├─{mysqld}(1462)
│ ├─{mysqld}(1463)
│ ├─{mysqld}(1464)
│ ├─{mysqld}(1465)
│ ├─{mysqld}(1466)
│ ├─{mysqld}(1468)
│ ├─{mysqld}(1469)
│ ├─{mysqld}(1470)
│ ├─{mysqld}(1471)
│ ├─{mysqld}(1472)
│ ├─{mysqld}(1473)
│ ├─{mysqld}(1637)
│ └─{mysqld}(1638)
├─polkitd(688)─┬─{polkitd}(695)
│ ├─{polkitd}(699)
│ ├─{polkitd}(702)
│ ├─{polkitd}(706)
│ ├─{polkitd}(707)
│ └─{polkitd}(708)
├─rsyslogd(938)─┬─{rsyslogd}(1019)
│ └─{rsyslogd}(1074)
├─sshd(933)───sshd(1647)───bash(1650)───pstree(1691)
├─systemd-journal(513)
├─systemd-logind(698)
├─systemd-udevd(547)
├─tuned(935)─┬─{tuned}(1625)
│ ├─{tuned}(1626)
│ ├─{tuned}(1628)
│ └─{tuned}(1636)
└─vsftpd(940)

我使用的是centos7.9,因此systemd(1)是第一个进程,作为所有其他进程的父进程。因为最近在学习中看到了相关的命令,所以在这里学习记录一下。

Init架构

系统的运行级别

Init架构中存在7个运行级别:

级别 功能
0 Shutdown(关机)
1 Single User Mode(单用户模式)
2 Multiuser mode without networking(断网多用户模式)
3 Multiuser mode with networking(联网多用户模式)默认
4 Unused(未使用)
5 Multiuser mode with networking and GUI(图形化界面的联网多用户模式)
6 Reboot(重启)

配置文件/etc/inittab决定以哪种方式运行系统,它是系统在启动init daemon时读取的第一个文件,默认是以3来启动。当然对于Centos7来说,这个文件已经没有用了,文件内容:

[root@www ~]# cat /etc/inittab
# inittab is no longer used when using systemd.
#
# ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# Ctrl-Alt-Delete is handled by /usr/lib/systemd/system/ctrl-alt-del.target
#
# systemd uses 'targets' instead of runlevels. By default, there are two main targets:
#
# multi-user.target: analogous to runlevel 3
# graphical.target: analogous to runlevel 5
#
# To view current default target, run:
# systemctl get-default
#
# To set a default target, run:
# systemctl set-default TARGET.target

Init架构的服务

Centos6,可以通过service命令来启动相应的服务

service network restart

/etc/rc.d/init.d存放着能够通过service命令管理的服务,通过按照相应的规则编写好对应的脚本,放到/etc/rc.d/init.d里面,就可以通过service命令来管理。在/etc/rc.d/文件夹里面,还存在/etc/rc.d/rc{0..6}.d文件夹,其中数字就是对应于Init架构中的7个级别,当系统以相应的级别开机或关机的时候,就会直接启动对应那个级别的文件夹里面的脚本。在/etc下存在软链接指向这几个目录:

[root@www etc]# ll init.d rc{0..6}.d rc.local -d
lrwxrwxrwx. 1 root root 11 Apr 9 13:33 init.d -> rc.d/init.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc0.d -> rc.d/rc0.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc1.d -> rc.d/rc1.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc2.d -> rc.d/rc2.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc3.d -> rc.d/rc3.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc4.d -> rc.d/rc4.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc5.d -> rc.d/rc5.d
lrwxrwxrwx. 1 root root 10 Apr 9 13:33 rc6.d -> rc.d/rc6.d
lrwxrwxrwx. 1 root root 13 Apr 9 13:34 rc.local -> rc.d/rc.local

我们以级别3为例,查看相应的文件:

[root@www rc3.d]# pwd
/etc/rc.d/rc3.d
[root@www rc3.d]# ll
total 0
lrwxrwxrwx. 1 root root 20 Apr 9 13:34 K50netconsole -> ../init.d/netconsole
lrwxrwxrwx. 1 root root 17 Apr 9 13:34 S10network -> ../init.d/network

可以看到这里面的文件,其实/etc/rc.d/init.d中脚本的软链接,并且名字也有所不同,原因在于Init架构在执行相应的脚本时,是根据脚本的名字来执行的即:

  • S:即Start,系统开机时执行
  • K:即Kill,系统关机时执行
  • 数字:执行的顺序
  • 最后才是脚本的名字
    虽然自从Centos7后,就有Systemd架构来代替Init架构,但是在Centos7中依然兼容了Init架构。

Init架构的启动

当我们打开给Linux系统的电脑开机的时候,BIOS 会从非易失性存储器中加载,并执行上电自检,之后BIOS会检测系统资源,然后会查找硬盘的主引导记录(MBR),MBR会初始化引导程序如GRBU,GRUB加载内核,内核会执行/sbin/init程序,其就会成为Pid = 1的所有Linux进程的父进程,然后/sbin/init会读取/etc/inittab文件,确定操作系统的运行级别,从文件/etc/fstab里查找分区表信息进行相应的挂载,然后按照运行级别执行/etc/rc.d/rcX.d里面的脚本,按顺序一个一个执行,每次只启动一个服务。关机过程差不多是相反,首先Init停止所有服务,最后阶段会卸载文件系统。

Systemd架构

一直以来,Centos都是采用Init架构,但是Init架构启动慢,需要串行启动,即进程是一个接着一个启动,只有当前一个进程启动成功,才会去启动下一个进程,同时启动进程的脚本比较复杂,因此Centos7之后,Systemd架构取代了Init架构,其可以做到并行启动,减少系统引导时间和计算开销。同时其为系统的启动和管理提供了完整的解决方案,如下图所示,Systemd架构及其复杂。

Systemd unit

Systemd可以管理系统的所有资源,并把这些资源统一称为unit。对应的unit有12种。

unit 分类

unit类型 文件后缀 描述
Service .service 系统服务,包括启动,重启,关闭服务的相关指令
Target .target 定义了一组unit的集合,一般作为unit启动的同步点,某个Target启动成功对应着一组相关的Service启动成功
Automount .automount 系统引导时会进行自动挂载的挂载点
Mount .mount systemd管理的文件系统挂载点
Path .path 定义了一条用于基于路径激活服务的文件路径。例如,可以基于某一条文件路径的状态(是否存在等)来启动某个服务。
Scope .scope 定义了来自systemd总线接口的信息,通常用来管理额外的系统进程
Slice .slice 定义了资源限额,基于Linux cgroup nodes实现。
Snapshot .snapshot 当前的systemd状态,通常在对systemd做修改后回滚使用
Socket .socket 定义了进程间通信使用的socket,往往socket会与service相关联
Swap .swap 定义了系统中的交换空间
Timer .timer 定义了一个定时激活另一个单元的定时器

unit 的存放路径

路径 说明
/etc/systemd/system systemctl enable命令创建的systemd unit文件将存放在此处,实际上是指向/usr/lib/systemd/system的软链接。系统管理员自定义的unit也存放在该目录下。默认在这里读取文件
/run/systemd/system 服务运行时产生的相关unit都存放在这个目录下
/usr/lib/systemd/system 系统或第三方软件安装时添加的unit放在这个目录下

常用的unit

可以利用man 5 systemd.unit类型去查看帮助文档,如man 5 systemd.slice,里面包括怎么写配置文件。这里简单介绍一下常用的unit,包括ServiceTarget

Service 简单介绍

Service类型是最常用的unit,主要是用来启动像httpdsshd这样的服务的配置文件,对应的文件名是httpd.servicessh.d.service,可以使用systemctl cat sshd.service

[root@www etc]# systemctl cat sshd.service
# /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

可以看到比较多字段,接下来我们简单了解一下:
# /usr/lib/systemd/system/sshd.service给出了对应的路径,一个unit包括三个字段[Unit][Install][Unit类型],这里Service类型对应的就是[Service]

  • [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 运行必须满足的条件,否则会报启动失败
    对于sshd.serviceDescription=OpenSSH server daemon给出了简单描述,Documentation=man:sshd(8) man:sshd_config(5)给出了文档信息,After=network.target sshd-keygen.service表明如果network.targetsshd-keygen.service要启动,那么sshd.service需要在这两个之后启动。Wants=sshd-keygen.service表明sshd.servicesshd-keygen.service有弱依赖关系,即使sshd-keygen.service未启动,启动失败或者停止服务也不会影响sshd.service的运行。
  • [Service]:定义了unit的服务配置:
    Type:定义启动时的进程行为。它有以下几种值。
    Type=simple:默认值,执行ExecStart指定的命令,启动主进程
    Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
    Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
    Type=dbus:当前服务通过D-Bus启动
    Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
    Type=idle:若有其他任务执行完毕,当前服务才会运行
    ExecStart:启动当前服务的命令
    ExecStartPre:启动当前服务之前执行的命令
    ExecStartPost:启动当前服务之后执行的命令
    ExecReload:重启当前服务时执行的命令
    ExecStop:停止当前服务时执行的命令
    ExecStopPost:停止当其服务之后执行的命令
    RestartSec:自动重启当前服务间隔的秒数
    Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog、no。no(默认值):退出后不会重启,on-success:只有正常退出时(退出状态码为0),才会重启,on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启,on-abnormal:只有被信号终止和超时,才会重启,on-abort:只有在收到没有捕捉到的信号终止时,才会重启,on-watchdog:超时退出,才会重启,always:不管是什么退出原因,总是重启
    TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
    Environment:指定环境变量
    EnvironmentFile:指定加载一个包含服务所需的环境变量列表的文件,文件中的每一行都是一个环境变量的定义
    KillMode:定义 Systemd 如何停止 sshd 服务。可以设置为:control-group(默认值):当前控制组里面的所有子进程,都会被杀掉,process:只杀主进程,mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号,none:没有进程会被杀掉,只是执行服务的 stop 命令。
    对于sshd.serviceType=notify表明当前服务启动完毕,会通知Systemd,再继续往下执行,EnvironmentFile=/etc/sysconfig/sshd从配置文件/etc/sysconfig/sshd中获取环境变量,最重要的就是这个执行命令ExecStart=/usr/sbin/sshd -D $OPTIONS,重启当前服务时执行的命令为ExecReload=/bin/kill -HUP $MAINPIDKillMode=process表示只停止主进程,不停止任何sshd子进程,即子进程打开的 SSH session仍然保持连接。这个设置不太常见,但对sshd很重要,否则你停止服务的时候,会连自己打开的 SSH session一起杀掉。Restart=on-failure表明出现任何意外的失败都重启,RestartSec=42s表明在重启sshd服务之前要等待42s
  • [Install]
    用来定义如何启动,以及是否开机启动
    WantedBy:它的值是一个或多个 Target,当前 unit 设置为开机启动时,软链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中,表示该服务所在的Target
    RequiredBy:它的值是一个或多个 Target,当前 unit 开机启动时,软链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中
    Alias:当前 unit 可用于启动的别名
    Also:当前 unit 激活(enable)时,会被同时激活的其他 unit
    对于sshd.serviceWantedBy=multi-user.target表明它是属于multi-user.target的,这个很重要,它可以设置开机自动启动,当我们用systemctl enable sshd时会在/etc/systemd/system/multi-user.target目录创建软链接到/usr/lib/systemd/system/sshd.serviceSystemd默认启动的Targetdefault.target,而default.targetmulti-user.targetgraphical.target的软链接,可以通过systemctl get-default查询到。
    [root@www etc]# systemctl get-default
    multi-user.target
    当使用命令时,不指定unit类型时,默认是Service类型,例如systemctl status sshd,查看服务状态
    [root@www init.d]# systemctl status sshd
    ● sshd.service - OpenSSH server daemon
    Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
    Active: active (running) since Sat 2024-04-13 16:35:12 CST; 17h ago
    Docs: man:sshd(8)
    man:sshd_config(5)
    Main PID: 933 (sshd)
    CGroup: /system.slice/sshd.service
    └─933 /usr/sbin/sshd -D

    Apr 13 16:35:12 www.a.org systemd[1]: Starting OpenSSH server daemon...
    Apr 13 16:35:12 www.a.org sshd[933]: Server listening on 0.0.0.0 port 22.
    Apr 13 16:35:12 www.a.org sshd[933]: Server listening on :: port 22.
    Apr 13 16:35:12 www.a.org systemd[1]: Started OpenSSH server daemon.
    Apr 13 16:35:27 www.a.org sshd[1647]: Accepted password for root from 172.16.34.145 port 2454 ssh2
    上面的输出含义:
    sshd.service行:服务的基本介绍
    Loaded行:配置文件的位置,是否设为开机启动,enabled表示开机自动启动,preset: enabled表示软件安装后默认开机自动启动。
    Active行:表示服务的运行状态为正在运行
    Docs:文档信息
    Main PID:主进程号
    CGroup块:应用的子进程
    日志块:最下面的带有时间的

Target 简单介绍

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

[root@www etc]# systemctl cat multi-user.target
# /usr/lib/systemd/system/multi-user.target
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes

Target也有自己的配置:
# /usr/lib/systemd/system/multi-user.target对应的目录位置
[Unit] 定义了unit的基本信息。

Description:基本描述
Documentation:对应的文档
Requires:当前 unit 依赖的其他 unit,如果它们没有运行,当前 unit 会启动失败
Conflicts:这里指定的 unit 不能与当前 unit 同时运行
After:如果该字段指定的 unit 也要启动,那么必须在当前 unit 之前启动
AllowIsolate:是否允许使用systemctl isolate命令切换到multi-user.target

对于multi-user.target,基本描述和文档分别为Description=Multi-User SystemDocumentation=man:systemd.special(7)Requires=basic.target表明需要同basic.target一起运行,Conflicts=rescue.service rescue.target表明和rescue.service rescue.target冲突不能一起运行,After=basic.target rescue.service rescue.target表明如果basic.target和rescue.service rescue.target要启动,multi-user.target需要在他们启动之后启动,AllowIsolate=yes表明允许使用systemctl isolate命令切换到multi-user.target
在前面介绍了Init架构的运行级别,在Systemd架构中也存在类似的概念,主要是通过Target来定义系统的运行模式,对应的关系如下:

Init架构运行等级 Systemd架构的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 重启系统
emergency emergency.target 紧急恢复状态
Systemd默认启动的Targetdefault.target,而default.targetmulti-user.targetgraphical.target的软链接,可以通过systemctl get-default查询到。
[root@www etc]# systemctl get-default
multi-user.target

日志管理

Systemd 统一管理所有Unit的启动日志。我们可以只用journalctl一个命令,查看所有日志(内核日志和应用日志),其从/var/log/messages中获取日志信息,存放在/run/log/journal/下。配置文件是/etc/systemd/journald.conf

Systemd 的启动

  1. 当我们打开给Linux系统的电脑开机的时候,BIOS 会从非易失性存储器中加载,并执行上电自检,之后BIOS会检测系统资源,然后会查找硬盘的主引导记录(MBR),MBR会初始化引导程序如GRBU或者LILO。

  2. MBR从GRBU或LILO引导程序读取相关信息并初始化内核。内核执行Systemd,之后的启动就交给Systemd了。Systemd使用Target来处理引导和服务管理过程。Target文件被用于分组不同的引导单元以及启动同步进程。

  3. Systemd执行的第一个Targetdefault.target,并递归的处理它的依赖关系,default.target实际上是指向multi-user.target或者graphical.target的软链接。

    [root@www ~]# systemctl cat default.target
    # /usr/lib/systemd/system/multi-user.target
    # This file is part of systemd.
    #
    # systemd is free software; you can redistribute it and/or modify it
    # under the terms of the GNU Lesser General Public License as published by
    # the Free Software Foundation; either version 2.1 of the License, or
    # (at your option) any later version.

    [Unit]
    Description=Multi-User System
    Documentation=man:systemd.special(7)
    Requires=basic.target
    Conflicts=rescue.service rescue.target
    After=basic.target rescue.service rescue.target
    AllowIsolate=yes
  4. 根据依赖关系,需要先启动sysinit.target,basic.target来初始化系统。

  5. multi-user.target会启动/etc/systemd/system/multi-user.target.wants下的服务,为多用户支持设定系统环境。非root用户会在这个阶段的引导过程中启用。防火墙相关的服务也会在这个阶段启动。利用这一点可以使得一些服务开机自动启动

  6. Systemd是可以兼容Init架构中的rc.local配置的,通过rc-local.service来实现兼容的,Systemd在启动的很早就会判断/etc/rc.local是否存在并且是可执行的,如果满足条件,那么Systemd会调用/usr/lib/systemd/system-generators/下的程序,把rc-local.service服务加入到default.target中来。这样在后面的执行时就会触发rc.local的运行,利用这一点我们可以实现程序的开机自动启动。

    ##################################### 启动流程图 #######################################
    cryptsetup-pre.target veritysetup-pre.target
    |
    (various low-level v
    API VFS mounts: (various cryptsetup/veritysetup devices...)
    mqueue, configfs, | |
    debugfs, ...) v |
    | cryptsetup.target |
    | (various swap | | remote-fs-pre.target
    | devices...) | | | |
    | | | | | v
    | v local-fs-pre.target | | | (network file systems)
    | swap.target | | v v |
    | | v | remote-cryptsetup.target |
    | | (various low-level (various mounts and | remote-veritysetup.target |
    | | services: udevd, fsck services...) | | |
    | | tmpfiles, random | | | remote-fs.target
    | | seed, sysctl, ...) v | | |
    | | | local-fs.target | | _____________/
    | | | | | |/
    \____|______|_______________ ______|___________/ |
    \ / |
    v |
    sysinit.target |
    | |
    ______________________/|\_____________________ |
    / | | | \ |
    | | | | | |
    v v | v | |
    (various (various | (various | |
    timers...) paths...) | sockets...) | |
    | | | | | |
    v v | v | |
    timers.target paths.target | sockets.target | |
    | | | | v |
    v \_______ | _____/ rescue.service |
    \|/ | |
    v v |
    basic.target rescue.target |
    | |
    ________v____________________ |
    / | \ |
    | | | |
    v v v |
    display- (various system (various system |
    manager.service services services) |
    | required for | |
    | graphical UIs) v v
    | | multi-user.target
    emergency.service | | |
    | \_____________ | _____________/
    v \|/
    emergency.target v
    graphical.target

    关于Linux的开机启动可以参考:Linux的启动过程

Systemd 相关的命令

系统相关

### systemd ###

systemctl --version #查看版本

systemctl reboot #重启系统

systemctl poweroff #关机

systemctl halt #关机

systemctl suspend #系统暂停

systemd-analyze #查看启动耗时

systemd-analyze plot > boot.svg #将启动耗时图形化展示

systemd-analyze blame #查看每个服务耗时

systemd-analyze critical-chain #查看瀑布状启动过程

systemd-analyze critical-chain sshd.service #查看指定服务的启动流

### hostnamectl ###

hostnamectl #查看主机

hostnamectl set-hostname WWW #设置主机名

### localectl ###

localectl #查看本地化设置

localectl set-locale LANG=en_GB.utf8 # 设置本地化语言

localectl set-keymap en_GB #设置本地化的键位图

### timedatectl ###

timedatectl #查看时间

timedatectl list-timezones #显示当前可用时区

timedatectl set-timezone America/New_York #设置当前时区

timedatectl set-time YYYY-MM-DD #设置当前时间,年月日

timedatectl set-time HH:MM:SS #设置当前时间,时分秒

### loginctl ###

loginctl list-sessions #列出当前session

loginctl list-users #列出当前登录用户

loginctl show-user root #列出指定用户信息

unit相关

man 5 systemd.slice #查看某种类型unit的文档

systemctl list-units #列出正在运行的 unit

systemctl list-units --all #列出所有的 unit,包括没有找到配置文件的或者启动失败的

systemctl list-units --all --state=inactive #列出所有没有运行的 unit

systemctl list-units --failed #列出所有加载失败的 unit

systemctl list-units --type=service #列出所有正在运行的、类型为 service 的 unit

systemctl status #显示系统状态

systemctl status ssh.d.service #查看单个unit状态

systemctl -H root@master status sshd.service #查看远程主机单个unit状态

systemctl is-active sshd.service #查看某个unit是否运行

systemctl is-failed sshd.service #查看某个unit是否启动失败

systemctl is-enabled sshd.service #查看某个unit是否开机自动启动

systemctl start sshd.service #启动某个unit

systemctl stop sshd.service #停止某个unit

systemctl restart sshd.service #重启某个unit

systemctl enable sshd.service #设置某个unit开机自启

systemctl enable sshd.service --now #设置某个unit开机自启,并重启

systemctl status sshd.service #查看某个unit的运行状态

systemctl disenable sshd.service #设置某个unit开机不自启

systemctl kill sshd.service #杀掉该unit的所有子进程

systemctl reload sshd.service #重新加载unit的配置文件

systemctl daemon-reload #重载所有修改过的配置文件

systemctl show sshd.service #显示某个unit的所有底层参数

systemctl show -p CPUShares sshd.service #显示某个unit的指定属性的值

systemctl set-property sshd.service CPUShares=500 #设置某个unit的指定属性

systemctl list-dependencies sshd.service #列出unit的依赖关系,不显示Target

systemctl list-dependencies --all sshd.service #列出unit的所有依赖关系

systemctl list-unit-files #列出所有的unit配置文件,配置文件有状态有:enabled:开机自启,disenabled:开机不自启,static:该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖,masked:该配置文件被禁止建立启动链接

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

systemctl list-units -t service --all #列出所有的指定unit的配置文件 -t就是type的意思

systemctl cat sshd.service #查看某个配置文件

systemctl edit sshd.service #编辑某个配置文件

systemctl get-default #查看启动时的默认Target

systemctl set-default multi-user.target #设置默认启动的Target

systemctl isolate multi-user.target #切换 Target 时,关闭前一个 Target 里面所有不属于后一个 Target 的进程,默认不关闭前一个 Target 启动的进程

日志相关

journalctl #查看日志,默认只保存本次启动的日志

journalctl -k #查看内核日志,不显示应用日志

journalctl -b # 查看系统本次启动的日志
journalctl -b -0

journalctl -b -1 # 查看系统上次启动的日志,需要修改配置文件,保存上次启动的日志

# 查看指定时间的日志
journalctl --since="2020-10-1 15:16:17"
journalctl --since "30 min ago"
journalctl --since yesterday
journalctl --since "2020-03-12" --until "2024-03-13 05:00"
journalctl --since 10:00 --until "2 hour ago"

journalctl -n # 显示尾部的最新10行日志

journalctl -n 20 # 显示尾部指定行数的日志

journalctl -f # 实时滚动显示最新日志

journalctl /usr/lib/systemd/systemd # 查看指定服务的日志

journalctl _PID=1 #查看指定进程的日志

journalctl /usr/bin/bash # 查看某个路径的脚本的日志

journalctl _UID=33 --since today # 查看指定用户的日志

# 查看某个 unit 的日志
journalctl -u sshd.service
journalctl -u sshd.service --since today

journalctl -u sshd.service -f # 实时滚动显示某个 Unit 的最新日志

journalctl -u nginx.service -u php-fpm.service --since today # 合并显示多个 Unit 的日志

# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
journalctl -p err -b

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

journalctl -b -u sshd.service -o json # 以 JSON 格式(单行)输出

journalctl -b -u sshd.service -o json-pretty # 以 JSON 格式(多行)输出,可读性更好

journalctl --disk-usage # 显示日志占据的硬盘空间

journalctl --vacuum-size=1G # 指定日志文件占据的最大空间

journalctl --vacuum-time=1years # 指定日志文件保存多久

systemd-

通过在终端输入systemd-,然后Tab补全就可以查看相应的命令,这些命令是systemd架构提供的可用命令,平时很少用到。

创建自己的Service

  1. 创建配置文件
    vim /etc/systemd/system/hello.service
    #### 文件内容
    [Unit]
    Description=Hello

    [Service]
    ExecStart=/usr/bin/python /root/hello.py
    Restart=on-failure

    [Install]
    WantedBy=multi-user.target
  2. 创建python脚本文件
    vim /root/hello.py
    #### 脚本内容
    import logging
    import time
    logging.basicConfig(format='Date-Time : %(asctime)s : Line No. : %(lineno)d - %(message)s', level = logging.DEBUG)
    while True:
    logging.debug("A Debug logging Message")
    time.sleep(10)
  3. 启动服务,并设置开机自启
    systemctl daemon-reload # 编写后需要重新加载新的配置文件
    systemctl start hello.service #启动服务
    systemctl enable hello.service #设置开机自动启动
    systemctl status hello.service #查看状态

    [root@www ~]# systemctl status hello.service -l
    ● hello.service - Hello
    Loaded: loaded (/etc/systemd/system/hello.service; enabled; vendor preset: disabled)
    Active: active (running) since Sun 2024-04-14 11:27:37 CST; 2min 17s ago
    Main PID: 8128 (python)
    CGroup: /system.slice/hello.service
    └─8128 /usr/bin/python /root/hello.py

    Apr 14 11:28:17 www.a.org python[8128]: Date-Time : 2024-04-14 11:28:17,540 : Line No. : 5 - A Debug logging Message
    Apr 14 11:28:27 www.a.org python[8128]: Date-Time : 2024-04-14 11:28:27,549 : Line No. : 5 - A Debug logging Message
    Apr 14 11:28:37 www.a.org python[8128]: Date-Time : 2024-04-14 11:28:37,580 : Line No. : 5 - A Debug logging Message
    Apr 14 11:28:47 www.a.org python[8128]: Date-Time : 2024-04-14 11:28:47,612 : Line No. : 5 - A Debug logging Message
    Apr 14 11:28:57 www.a.org python[8128]: Date-Time : 2024-04-14 11:28:57,619 : Line No. : 5 - A Debug logging Message
    Apr 14 11:29:07 www.a.org python[8128]: Date-Time : 2024-04-14 11:29:07,638 : Line No. : 5 - A Debug logging Message
    Apr 14 11:29:17 www.a.org python[8128]: Date-Time : 2024-04-14 11:29:17,642 : Line No. : 5 - A Debug logging Message
    Apr 14 11:29:27 www.a.org python[8128]: Date-Time : 2024-04-14 11:29:27,701 : Line No. : 5 - A Debug logging Message
    Apr 14 11:29:37 www.a.org python[8128]: Date-Time : 2024-04-14 11:29:37,728 : Line No. : 5 - A Debug logging Message
    Apr 14 11:29:47 www.a.org python[8128]: Date-Time : 2024-04-14 11:29:47,737 : Line No. : 5 - A Debug logging Message

    systemctl restart hello #重启服务
    ps aux | grep hello #查看进程
    [root@www ~]# ps aux | grep hello
    root 8347 0.0 0.2 138728 5404 ? Ss 11:31 0:00 /usr/bin/python /root/hello.py
    root 8373 0.0 0.0 112812 976 pts/0 S+ 11:31 0:00 grep --color=auto hello

    systemctl stop hello #停止服务

参考