关于Linux中控制群组(cgroup)的一些笔记

简介: 不加思考地滥读或无休止地读书,所读过的东西无法刻骨铭心,其大部分终将消失殆尽。——叔本华

不加思考地滥读或无休止地读书,所读过的东西无法刻骨铭心,其大部分终将消失殆尽。——叔本华

写在前面


不加思考地滥读或无休止地读书,所读过的东西无法刻骨铭心,其大部分终将消失殆尽。——叔本华


容器使用cgroup对资源进行限制

容器内存限制:-m 200M

┌──[root@liruilongs.github.io]-[/]
└─$ docker run -itd --name=c2 -m 200M  centos
3b2df1738e84159f4fa02dadbfc285f6da8ddde4d94cb449bc775c9a70eaa4ea
┌──[root@liruilongs.github.io]-[/]
└─$ docker stats
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O     BLOCK I/O         PIDS
3b2df1738e84   c2        0.00%     528KiB / 200MiB       0.26%     648B / 0B   0B / 0B           1
55e45b34d93d   c1        0.00%     8.684MiB / 3.843GiB   0.22%     648B / 0B   30.5MB / 11.5MB   2

对容器CPU的限制:-cpuset-cpus 0

┌──[root@liruilongs.github.io]-[/]
└─$ ps mo pid,psr $(pgrep cat)
┌──[root@liruilongs.github.io]-[/]
└─$ docker run -itd --name=c3 --cpuset-cpus 0 -m 200M  centos
a771eed8c7c39cd410bd6f43909a67bfcf181d87fcafffe57001f17f3fdff408

第 1 章 控制群组简介

1.1. 什么是控制群组

控制群组(control group)Linux kernel(Linux内核)的一项功能:

在一个系统中运行的层级制进程组,您可对其进行资源分配(如CPU时间、系统内存、网络带宽或者这些资源的组合)

通过使用cgroup ,系统管理员在分配、排序、拒绝、管理和监控系统资源等方面,可以进行精细化控制。硬件资源可以在应用程序和用户间智能分配,从而增加整体效率。

控制群组可对进程进行层级式分组并标记,并对其可用资源进行限制

传统情况下,所有的进程分得的系统资源数量相近,管理员用进程niceness值进行调节。

用niceness值进行调节,包含大量进程的应用程序可以比包含少量进程的应用程序获得更多资源,这与应用程序的重要程度无关。

通过将cgroup层级系统与systemd单位树捆绑, Linux 可以把资源管理设置从进程级别移至应用程序级别。

可以使用systemctl指令,或者通过修改systemd单位文件来管理系统资源。

在 Linux 7之前的版本中,系统管理员使用 libcgroup软件包中的cgconfig指令来建立 自定义cgroup层级。但现在,这个软件包已经过时也不被推荐使用,因为它很容易与默认的cgroup层级产生冲突。然而,在一些特定情况下, libcgroup仍然可用,如systemd不可用时,或使用net-prio子系统时。

上述工具提供了高阶接口,用与Linux kernel中的cgroup管控器(也称为子系统)互动。用于资源管理的主要cgroup管控器是cpu, memory和blkio

1.2. cgroup的默认层级

默认情况下, systemd会自动创建slice, scope和service单位的层级,来为cgroup树提供统一结构。使用systemctl指令,您可以通过创建自定义slice进一步修改此结构, systemd也自动为/sys/fs/cgroup/目录中重要的kernel资源管控器挂载层级。

在系统的开机阶段,systemd 会把支持的 controllers (subsystem 子系统)挂载到默认的 /sys/fs/cgroup/ 目录下面:

┌──[root@liruilongs.github.io]-[~]
└─$ ls /sys/fs/cgroup/
blkio  cpuacct      cpuset   freezer  memory   net_cls,net_prio  perf_event  systemd
cpu    cpu,cpuacct  devices  hugetlb  net_cls  net_prio          pids
┌──[root@liruilongs.github.io]-[~]
└─$ ll /sys/fs/cgroup/
total 0
drwxr-xr-x 5 root root  0 Oct 13 01:53 blkio
lrwxrwxrwx 1 root root 11 Oct 13 01:53 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Oct 13 01:53 cpuacct -> cpu,cpuacct
drwxr-xr-x 5 root root  0 Oct 13 01:53 cpu,cpuacct
drwxr-xr-x 2 root root  0 Oct 13 01:53 cpuset
drwxr-xr-x 5 root root  0 Oct 13 01:53 devices
drwxr-xr-x 2 root root  0 Oct 13 01:53 freezer
drwxr-xr-x 2 root root  0 Oct 13 01:53 hugetlb
drwxr-xr-x 5 root root  0 Oct 13 01:53 memory
lrwxrwxrwx 1 root root 16 Oct 13 01:53 net_cls -> net_cls,net_prio
drwxr-xr-x 2 root root  0 Oct 13 01:53 net_cls,net_prio
lrwxrwxrwx 1 root root 16 Oct 13 01:53 net_prio -> net_cls,net_prio
drwxr-xr-x 2 root root  0 Oct 13 01:53 perf_event
drwxr-xr-x 2 root root  0 Oct 13 01:53 pids
drwxr-xr-x 5 root root  0 Oct 13 01:53 systemd
┌──[root@liruilongs.github.io]-[~]
└─$

除了 systemd 目录外,其它目录都是对应的 subsystem/sys/fs/cgroup/systemd 目录是 systemd 维护的自己使用的非 subsystem cgroups 层级结构。

systemd 的单位类型

系统中运行的所有进程,都是 systemd init 进程的子进程。在资源管控方面,systemd 提供了三种单位类型:

service

service : 一个或一组进程,由 systemd 依据单位配置文件启动。service 对指定进程进行封装,这样进程可以作为一个整体被启动或终止。service 参照以下方式命名:

name.service # 其中,name 代表服务名称。
Undefined

scope

scope : 一组外部创建的进程。由强制进程通过 fork() 函数启动和终止、之后被 systemd 在运行时注册的进程,scope 会将其封装。例如:用户会话、 容器和虚拟机被认为是 scope。scope 的命名方式如下:

name.scope #其中,name 代表 scope 名称。
Undefined

slice

slice : 一组按层级排列的单位。slice 并不包含进程,但会组建一个层级,并将 scope 和 service 都放置其中。真正的进程包含在 scope 或 service 中。在这一被划分层级的树中,每一个 slice 单位的名字对应通向层级中一个位置的路径。小横线("-")起分离路径组件的作用。例如,如果一个 slice 的名字是:

parent-name.slice
Undefined
这说明 parent-name.sliceparent.slice 的一个子 slice。这一子 slice 可以再拥有自己的子 slice,被命名为: parent-name-name2.slice,以此类推。
-.slice
Undefined

service、scopeslice 单位直接映射到 cgroup 树中的对象。当这些单位被激活,它们会直接一一映射到由单位名建立的 cgroup 路径中。例如,ex.service 属于 test-waldo.slice,会直接映射到 cgroup test.slice/test-waldo.slice/ex.service/ 中。

service、scope slice 是由系统管理员手动创建或者由程序动态创建的。默认情况下, 操作系统会定义一些运行系统必要的内置 service。另外,默认情况下,系统会创建四种 slice:

slice: 描述
-.slice 根 slice;
system.slice 所有系统 service 的默认位置;
user.slice 所有用户会话的默认位置;
machine.slice 所有虚拟机和 Linux 容器的默认位置。

请注意,所有的用户会话、虚拟机和容器进程会被自动放置在一个单独的 scope 单元中。而且,所有的用户会分得一个隐含子 slice(implicit subslice)。除了上述的默认配置,系统管理员可能会定义新的 slice,并将 service 和 scope 置于其中。

├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
├─docker
│ ├─3254bcd54a7b2b1a5ece2ca873ab18c3215484e6b4f83617a522afe4e853c378
│ │ ├─11885 /home/weave/runsvinit
│ │ ├─11902 /sbin/runsvdir /etc/service
│ │ ├─11903 runsv probe
│ │ ├─11904 runsv app
│ │ ├─11907 scope-probe --mode probe --probe.docker=true
│ │ └─11908 scope-app --mode app --probe.docker=true
│ ├─b867272463dffc7a2f698848a622e33ed59a2176da89b99038e451eaf181bc57
│ │ └─11484 /usr/bin/cadvisor -logtostderr
│ ├─a771eed8c7c39cd410bd6f43909a67bfcf181d87fcafffe57001f17f3fdff408
│ │ ├─11310 /bin/bash
│ │ └─11361 bash
│ ├─3b2df1738e84159f4fa02dadbfc285f6da8ddde4d94cb449bc775c9a70eaa4ea
│ │ └─11086 /bin/bash
│ └─55e45b34d93d0a36a06283c90e7da9097ad3d85d26dfbdc9d07d2e45aeced8f1
│   └─10677 /bin/bash
├─user.slice
│ └─user-0.slice
│   ├─session-169.scope
│   │ ├─26654 sshd: root@pts/2
│   │ ├─26656 -bash
│   │ └─26925 systemd-cgls
│   ├─session-166.scope
│   │ ├─25790 sshd: root@pts/1
│   │ └─25792 -bash
│   └─session-158.scope
│     ├─24025 sshd: root@pts/0
│     └─24027 -bash
└─system.slice
  ├─docker.service
  │ ├─10151 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd...
  │ ├─11445 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080...
  │ └─11452 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 8080 -con...
  ├─postfix.service
  │ ├─ 1027 /usr/libexec/postfix/master -w
  │ ├─ 1043 qmgr -l -t unix -u
  │ └─26337 pickup -l -t unix -u
  ├─tuned.service
  │ └─943 /usr/bin/python -Es /usr/sbin/tuned -l -P
  ├─sshd.service
  │ └─942 /usr/sbin/sshd -D
  ├─containerd.service
  │ ├─  946 /usr/bin/containerd
  │ ├─10656 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 55e45b34d93d...
  │ ├─11066 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 3b2df1738e84...
  │ ├─11288 /usr/bin/containerd-shim-runc-v2 -namespace moby -id a771eed8c7c3...
  │ ├─11465 /usr/bin/containerd-shim-runc-v2 -namespace moby -id b867272463df...
  │ └─11865 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 3254bcd54a7b...
  ├─crond.service
  │ └─605 /usr/sbin/crond -n
  ├─rsyslog.service
  │ └─600 /usr/sbin/rsyslogd -n
  ├─dbus.service
  │ └─590 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile -...
  ├─irqbalance.service
  │ └─589 /usr/sbin/irqbalance --foreground
  ├─polkit.service
  │ └─586 /usr/lib/polkit-1/polkitd --no-debug
  ├─vmtoolsd.service
  │ └─583 /usr/bin/vmtoolsd
  ├─vgauthd.service
  │ └─582 /usr/bin/VGAuthService -s
  ├─chronyd.service
  │ └─594 /usr/sbin/chronyd
  ├─systemd-logind.service
  │ └─542 /usr/lib/systemd/systemd-logind
  ├─auditd.service
  │ └─495 /sbin/auditd
  ├─systemd-udevd.service
  │ └─463 /usr/lib/systemd/systemd-udevd
  ├─system-getty.slice
  │ └─getty@tty1.service
  │   └─612 /sbin/agetty --noclear tty1 linux
  └─systemd-journald.service
    └─438 /usr/lib/systemd/systemd-journald

service 和 scope 包含进程,但被放置在不包含它们自身进程的 slice 里。唯一例外是位于特殊 systemd.slice 中的 PID 1。请注意,-.slice 未被显示,因为它被整体树的根隐性识别。

service 和 slice 单位可通过永久单位文件来配置;或者对 PID 1 进行 API 调用,在运行时动态创建。scope 单位只能以第一种方式创建。API 调用动态创建的单位是临时的,并且仅在运行时存在。一旦结束、被关闭或者系统重启,临时单位会被自动释放。

1.3. Linux Kernel 的资源管控器

资源管控器(也称为 cgroup 子系统)代表一种单一资源:如 CPU 时间或者内存。Linux kernel 提供一系列资源管控器,由 systemd 自动挂载。如需参考目前已挂载的资源管控器列表,请参见 /proc/cgroups,或使用 lssubsys 监控工具。在 Linux 7 中,systemd 默认挂载以下管控器:

Linux 7 中可用的管控器

管控器 dest
blkio 对输入 ∕ 输出访问存取块设备设定权限;
cpu 使用 CPU 调度程序让 cgroup 的任务可以存取 CPU。它与 cpuacct 管控器一起挂载在同一 mount 上;
cpuacct 自动生成 cgroup 中任务占用 CPU 资源的报告。它与 cpu 管控器一起挂载在同一 mount 上;
cpuset 给 cgroup 中的任务分配独立 CPU(在多芯系统中)和内存节点;
devices 允许或禁止 cgroup 中的任务存取设备;
freezer 暂停或恢复 cgroup 中的任务;
memory 对 cgroup 中的任务可用内存做出限制,并且自动生成任务占用内存资源报告;
net_cls 使用等级识别符(classid)标记网络数据包,这让 Linux 流量控制器(tc 指令)可以识别来自特定 cgroup 任务的数据包;
perf_event 允许使用 perf 工具来监控 cgroup;
hugetlb 允许使用大篇幅的虚拟内存页,并且给这些内存页强制设定可用资源量。

Linux Kernel 展示了一系列可用 systemd 配置的资源管控器可调参数。参数的详细描述请参阅 kernel 文档(kernel 管控器专项介绍 的参考列表)。

第 2 章 使用控制群组

概述与创建、管理控制群组相关的任务。systemd 是管理 cgroup 的推荐方式并会在将来版本中被支持,

2.1. 创建控制群组

systemd 的角度来看,cgroup 会连接到一个系统单位,此单位可用单位文件进行配置、用 systemd 命令列实用工具进行管理。根据应用的类型,您的资源管理设定可以是 transient(临时的) 或者 persistent(永久的)

要为服务创建 transient cgroup(临时 cgroup),请使用 systemd-run 指令启动此服务。如此,可以限制此服务在运行时所用资源。对 systemd 进行 API 调用,应用程序可以动态创建临时 cgroup。服务一旦停止,临时单位就会被自动移除。

要给服务分配 persistent cgroup(永久 cgroup),请对其单位配置文件进行编写系统重启后,此项配置会被保留,所以它可以用于管理自动启动的服务。请注意,scope 单位不能以此方式创建。

2.1.1. 用 systemd-run 创建临时 cgroup

systemd-run 指令用于 创建、启动临时 service 或 scope 单位,并在此单位中运行自定义指令在 service 单位中执行的指令在后台非同步启动,它们从 systemd 进程中被调用。在 scope 单位中运行的指令直接从 systemd-run 进程中启动,因此从调用方继承执行状态。此情况下的执行是同步的。

在一个指定 cgroup 中运行指令,请以 root 身份输入

systemd-run --unit=name --scope --slice=slice_name command
Undefined
name 代表您想要此单位被识别的名称。如果 --unit 没有被指定,单位名称会自动生成。建议选择一个描述性的名字,因为它将代表 systemctl 输出中的单位。在单位运行时期间,此名字需为独一无二的。
使用可选的 --scope 参数创建临时 scope 单位来替代默认创建的 service 单位。
--slice 选项,让您新近创建的 service scope 单位可以成为指定 slice 的一部分。用现存 slice(如 systemctl -t slice 输出所示)的名字替代 slice_name,或者通过传送一个独有名字来创建新 slice。默认情况下,service 和 scope 做为 system.slice 的一部分被创建。
用您希望在 service 单位中运行的指令替代 command。将此指令放置于 systemd-run 句法的最末端。这样,此指令的参数就不会与 systemd-run 参数混淆。
上述选项外,systemd-run 也有一些其它可用参数。例如,--description 可以创建对单位的描述;service 进程结束后,--remain-after-exit 可以收集运行时信息;--machine 选项可以在密闭容器中执行指令

用 systemd-run 来启动新 service

┌──[root@liruilongs.github.io]-[~]
└─$ systemd-run --unit=toptest --slice=test top -b
Running as unit toptest.service. #现在,toptest.service 名称可以与 systemctl 指令结合,以监控或修改 cgroup。
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl status toptest.service
● toptest.service - /usr/bin/top -b
   Loaded: loaded (/run/systemd/system/toptest.service; static; vendor preset: disabled)
  Drop-In: /run/systemd/system/toptest.service.d
           └─50-Description.conf, 50-ExecStart.conf, 50-Slice.conf
   Active: active (running) since Wed 2021-10-13 01:12:43 CST; 50s ago
 Main PID: 27671 (top)
   CGroup: /test.slice/toptest.service
           └─27671 /usr/bin/top -b

Oct 13 01:13:31 liruilongs.github.io top[27671]: 24025 root      20   0  145704   5332   4072 S   0.0  0.1   0:0... sshd
Oct 13 01:13:31 liruilongs.github.io top[27671]: 24027 root      20   0  116024   2812   1784 S   0.0  0.1   0:0... bash
Oct 13 01:13:31 liruilongs.github.io top[27671]: 24926 root      20   0       0      0      0 S   0.0  0.0   0:0...er/u+
Oct 13 01:13:31 liruilongs.github.io top[27671]: 25314 root      20   0       0      0      0 S   0.0  0.0   0:0...er/0+
Oct 13 01:13:31 liruilongs.github.io top[27671]: 25790 root      20   0  145704   5328   4072 S   0.0  0.1   0:0... sshd
Oct 13 01:13:31 liruilongs.github.io top[27671]: 25792 root      20   0  115784   2440   1636 S   0.0  0.1   0:0... bash
Oct 13 01:13:31 liruilongs.github.io top[27671]: 26067 root      20   0       0      0      0 S   0.0  0.0   0:0...er/0+
Oct 13 01:13:31 liruilongs.github.io top[27671]: 26337 postfix   20   0   89648   4028   3016 S   0.0  0.1   0:0...ickup
Oct 13 01:13:31 liruilongs.github.io top[27671]: 27425 root      20   0       0      0      0 S   0.0  0.0   0:0...er/1+
Oct 13 01:13:31 liruilongs.github.io top[27671]: 27530 root      20   0       0      0      0 S   0.0  0.0   0:0...er/1+
Hint: Some lines were ellipsized, use -l to show in full.
┌──[root@liruilongs.github.io]-[~]
└─$
┌──[root@liruilongs.github.io]-[~]
└─$ systemd-cgls
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
├─test.slice
│ └─toptest.service
│   └─27671 /usr/bin/top -b
├─docker
│ ├─3254bcd54a7b2b1a5ece2ca873ab18c3215484e6b4f83617a522afe4e853c378
│ │ ├─11885 /home/weave/runsvinit
│ │ ├─11902 /sbin/runsvdir /etc/service
│ │ ├─11903 runsv probe
........

2.1.2. 创建永久 cgroup

若要在系统启动时,配置一个自动启动的单位,请执行 systemctl enable 指令。自动运行此指令会在 /usr/lib/systemd/system/ 目录中创建单位文件。如要对 cgroup 做出永久改变,请添加或修改其单位文件中的配置参数。更多信息,请参阅〈第 2.3.2 节 “修改单位文件”〉。

2.2. 删除控制群组

临时 cgroup 所包含的进程一旦结束,临时 cgroup 就会被自动释放。通过将 --remain-after-exit 选项传递给 systemd-run,您可以在其进程结束后,让单位继续运行来收集运行时的信息。如要单位停止运行,请输入:

systemctl stop name.service
Undefined

如果您希望一个 service 停止运行,请将 name 替换成此 service 的名字。如要终止一个或多个单位中的进程,请以 root 身份输入:

systemctl kill name.service --kill-who=PID,... --signal=signal 
Undefined

用单位名(如 httpd.service)替代 name。使用 --kill-who cgroup 中挑选您希望结束的进程。如要同时终止多项进程,请传送一份 PID 的逗号分隔列表。用您希望发送至指定进程的 POSIX 信号类型替代 signal。默认情况下是 SIGTERM

当单位被禁用并且其配置文件通过运行(下列行)被删除,永久 cgroup 会被释放:

systemctl disable name.service  #name 代表您希望禁用的 service 名字。
Undefined

2.3. 修改 cgroup

所有被 systemd 监管的永久单位都在 /usr/lib/systemd/system/ 目录中有一个单位配置文件。如要修改 service 单位的参数,请修改此配置文件。可以手动完成或者从命令列界面使用 systemctl set-property 指令。

# 用您希望修改的 systemd 名字来替代 name,希望改动的参数名称来替代 parameter,希望分配给此参数的新值来替代 value。
systemctl set-property name parameter=value
Undefined

并非所有单位参数都能在运行时被修改,但是大多数与资源管控相关的参数是可以的,systemctl set-property 指令让您可以同时修改多项属性,所以相较于单独设定每项属性,推荐您使用此指令。

改动会立即生效并被写入单位文件,并在重启后保留。您可以传递 --runtime 选项,让设定变成临时设定

systemctl set-property --runtime name property=value
Undefined

2.3.1. 在命令列界面设定参数

systemctl set-property 指令让您可以在 应用程序运行时,持续修改资源管控设置。请以 root 身份使用下列句法来完成此项操作:

使用 systemctl set-property

# 如需使用命令列来限定 httpd.service 的 CPU 和内存占用量,请输入:
systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M
# 如希望此更改为临时更改,请添加 --runtime 选项:
systemctl set-property --runtime httpd.service CPUShares=600 MemoryLimit=500M
######################
┌──[root@liruilongs.github.io]-[~]
└─$ 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
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl set-property httpd.service BlockIOAccounting=true
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M
┌──[root@liruilongs.github.io]-[~]
└─$ cat  /etc/systemd/system/httpd.service.d/50-CPUShares.conf
[Service]
CPUShares=600
┌──[root@liruilongs.github.io]-[~]
└─$ cat  /etc/systemd/system/httpd.service.d/50-MemoryLimit.conf
[Service]
MemoryLimit=524288000
┌──[root@liruilongs.github.io]-[~]
└─$ cat  /etc/systemd/system/httpd.service.d/50-BlockIOAccounting.conf
[Service]
BlockIOAccounting=yes
┌──[root@liruilongs.github.io]-[~]
└─$

2.3.2. 修改单位文件

systemd service 单位文件提供一系列对资源管理有帮助的高级配置参数。这些参数与必须在 kernel 中启用的 Linux cgroup 管控器通讯。您可以使用这些参数管理 CPU、内存使用量、block IO和更多精细单位的属性。

管理 CPU

cpu 管控器在 kernel 中被默认启动,这可使所有系统 service 的可用 CPU 量相同,而与其所包含进程数量无关。此项默认设定可以使用 /etc/systemd/system.conf 配置文件中的 DefaultControllers 参数来修改。如需管理 CPU 的分配,请使用单位配置文件 [Service] 部分中的下列指令:

`CPUShares=value`

请用 CPU share 的数量代替 value。默认值为 1024,您可以增加此数值来给单位分配更多 CPU。此参数默认:CPUAccounting 已在单位文件中启用。
CPUShares 参数可以控制 cpu.shares 控制群组参数。

┌──[root@liruilongs.github.io]-[~]
└─$ cat /etc/systemd/system.conf | grep -i BlockIOAccounting
#DefaultBlockIOAccounting=no
┌──[root@liruilongs.github.io]-[~]
└─$ cat /etc/systemd/system.conf | grep -i CPUAccounting
#DefaultCPUAccounting=no
限定一个单位的 CPU 可用量
#若要为 Apache service 分配 1500 个 CPU share 而不是 1024 个,请修改 /usr/lib/systemd/system/httpd.service 单位文件中的 CPUShares 设置:
[Service]
CPUShares=1500
# 要应用此项修改,请重新载入 systemd 的配置并重启 Apache 来让修改过的 service 文件生效:
 systemctl daemon-reload
 systemctl restart httpd.service

内存管理

为限定单位可用内存大小,请使用单位配置文件 [Service] 部分中的下列指令:

MemoryLimit=value

cgroup 中执行的进程设定其可用内存的最大值,并用此值替代 value。请以千字节(Kilobyte)、兆字节(Megabyte)、千兆字节(Gigabyte)、太字节(Terabyte)为计量单位并使用 K、M、G、T 后缀来表示。同样,MemoryAccounting 参数必须在同一单元中启用
MemoryLimit 参数可以控制 memory.limit_in_bytes 控制群组参数

限制一个单位的可用内存量
#若要限定 Apache service 的最大可用内存为 1GB,请修改 /usr/lib/systemd/system/httpd.service 单位文件中的 MemoryLimit 设定:
[Service]
MemoryLimit=1G
#要应用此项修改,请重新载入 systemd 的配置并重启 Apache 来让修改过的 service 文件生效:
systemctl daemon-reload
systemctl restart httpd.service

管理 Block IO

如要管理 Block IO,请使用单位配置文件 [Service] 部分中的下列指令。下列指令假设 BlockIOAccounting 参数已启动:

BlockIOWeight=value

为已执行进程选取一个新的整体 block IO 权重,并以此替代 value。权重需在 10 到 1000 之间选择,默认值是 1000。

BlockIODeviceWeight=device_name value

请为 device_name 所指的设备选取 block IO 权重,并以此代替 value。用名称或者通向此设备的路径来代替 device_name。因为有 BlockIOWeight,您可以在 10 到 1000 之间选取权重值。

BlockIOReadBandwidth=device_name value

此指令可以为一个单位限定具体带宽。用设备名称或通向块设备节点的路径替换 device_name,value 代表带宽率。使用 K、M、G、T 后缀作为计量单位。没有后缀的值默认单位为 “字节/秒”。

BlockIOWriteBandwidth=device_name value

此指令可以给指定设备限定可写带宽。参数与可与 BlockIOReadBandwidth 一致。

限定一个单位 Block IO 的可用量
# 如要降低 Apache service 存取 /home/jdoe/ 目录 block IO 的权重,请将下列字符添加至 /usr/lib/systemd/system/httpd.service 单位文件:
[Service]
BlockIODeviceWeight=/home/jdoe 750
#如要设定 Apache 从 /var/log/ 目录读取的最大带宽为 5MB/秒,请使用下列句法:
[Service]
BlockIOReadBandwith=/var/log 5M
#如要应用此项修改,请重新载入 systemd 的配置并重启 Apache,这样所修改的 service 文件会生效:
systemctl daemon-reload
systemctl restart httpd.service
Undefined

管理其它系统资源

另有几种指令,可在单位文件中使用以协助管理资源。

DeviceAllow=device_name options
#此选项可以控制存取指定设备节点的次数。此处,device_name 代表通向设备节点的路径,
# 或者是 /proc/devices 中特定的设备组名称。用 r、w 和 m 的组合来替换 options,
# 以便单位读取、写入或者创建设备节点。
DevicePolicy=value
#此处,value 是以下三种之一。
# - strict :仅允许 DeviceAllow 指定的存取类型;
# - closed:允许对标准伪设备的存取,如:/dev/null、/dev/zero、/dev/full、/dev/random 和 /dev/urandom; 
# - auto:如果不显示 DeviceAllow,则允许对所有设备进行存取,此设定为默认设置。
Slice=slice_name
# 请用存放单位的 slice 名称替换 slice_name。默认名称是 system.slice。scope 单位不能以此方式排列,因为它们已与其父 slice 绑定。
ControlGroupAttribute=attribute value
# 此选项可以设定 Linux cgroup 管控器公开的多项控制群组参数。用您希望修改的低级别 cgroup 参数来替换 attribute,用此参数的新值来替换 value。
更改低级别 cgroup 的属性
#如果您希望更改 memory.swappiness 设置来重新设定 kernel 替换 cgroup 任务所用进程内存的趋势,请参阅〈Kernel 管控器专项介绍〉对内存管控器的介绍。如要将 Apache service 的 memory.swappiness 设为 70,请添加下列信息至 /usr/lib/systemd/system/httpd.service:
[Service]
ControlGroupAttribute=memory.swappiness 70
#要应用此项修改,请重新载入 systemd 的配置并重启 Apache 来让修改过的 service 文件生效:
systemctl daemon-reload
systemctl restart httpd.service
Undefined

2.4. 获得关于控制群组的信息

使用 systemctl 指令将系统单位列表并检查它们的状态。systemd-cgls 指令可以检查控制群组的层级,systemd-cgtop 可以监控控制群组的实时资源消耗。

2.4.1. 将单位列表

使用下列指令将系统中所有被激活单位列表:

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-units
UNIT                                            LOAD   ACTIVE SUB       DESCRIPTION
proc-sys-fs-binfmt_misc.automount               loaded active waiting   Arbitrary Executable File Formats File System Au
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda1.device loaded active 
................
以上所列结果包含四项:
UNIT 单位名称,也反映单位在 cgroup 树中的位置。 有三种单位类型与资源控制相关:slice、scope 和 service
LOAD 显示单位配置文件是否被正确装载。如果装载失败,文件会包含 error 而不是 loaded。其它单位装载状态有:stub、merged 和 masked
ACTIVE 高级单位的激活状态,是 SUB 的一般化。
SUB 低级单位的激活状态。可能值的范围取决于单位类型。
DESCRIPTION 描述单位内容和性能。

默认情况下,systemctl 只会列出被激活的单位(依据 ACTIVE 域中的高级激活状态)。使用 --all 选项可以查看未被激活的单位。如要限制结果列表中的信息量,请使用 --type (-t) 参数,此参数需要单位类型的逗号分隔列表,如:service 和 slice 或者单位装载状态,如:loaded 和 masked

使用 systemctl list-units

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl -t slice
UNIT                                              LOAD   ACTIVE SUB    DESCRIPTION
-.slice                                           loaded active active Root Slice
system-getty.slice                                loaded active active system-getty.slice
system-selinux\x2dpolicy\x2dmigrate\x2dlocal\x2dchanges.slice loaded active active system-selinux\x2dpolicy\x2dmigrate\x
system.slice                                      loaded active active System Slice
user-0.slice                                      loaded active active User Slice of root
user.slice                                        loaded active active User and Session Slice

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.

6 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
┌──[root@liruilongs.github.io]-[~]
└─$  systemctl -t service,masked
Unknown unit type or load state 'masked'.
Use -t help to see a list of allowed values.
┌──[root@liruilongs.github.io]-[~]
└─$  systemctl -t masked
0 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-unit-files
UNIT FILE                                     STATE
proc-sys-fs-binfmt_misc.automount             static
dev-hugepages.mount                           static
dev-mqueue.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
.......

在这里插入图片描述

2.4.2. 查看控制群组的层级

上述指令不会超越单位水平来显示 cgroup 中运行的真正进程。systemctl 结果也不会显示单位的层级。您可以使用 systemd-cgls 指令,根据 cgroup 将运行的进程分组来同时实现两者。 要显示您系统中的全部 cgroup 层级,请输入:

systemd-cgls
# 如要减少 systemd-cgls 的输出并查看层级的特定一部分,请执行:
systemd-cgls name
systemctl status httpd.service

在这里插入图片描述

除了上述工具,systemd 也提供了专门监控 Linux 的 machinectl 指令。

2.4.3. 查看资源管控器

上述的 systemctl 指令可以监控高级单位层级,但是不能显示 Linux kernel 的资源管控器被哪项进程使用。这些信息存储在专门的进程文件中,如要查阅这些文件,请以 root 身份输入:

# PID 代表您希望查看的进程 ID。
cat proc/PID/cgroup
┌──[root@liruilongs.github.io]-[~]
└─$ ps -ef | grep httpd | grep -v grep
root       1231      1  0 02:00 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     1232   1231  0 02:00 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     1233   1231  0 02:00 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     1234   1231  0 02:00 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     1235   1231  0 02:00 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     1236   1231  0 02:00 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
┌──[root@liruilongs.github.io]-[~]
└─$ cat /proc/1231/cgroup
# 默认情况下,此列表对所有 systemd 启动的单位一致,因为它自动挂载所有默认管控器
11:blkio:/system.slice/httpd.service
10:memory:/system.slice/httpd.service
9:freezer:/
8:perf_event:/
7:cpuacct,cpu:/system.slice/httpd.service
6:devices:/system.slice/httpd.service
5:pids:/
4:hugetlb:/
3:net_prio,net_cls:/
2:cpuset:/
1:name=systemd:/system.slice/httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$

2.4.4. 监控资源消耗量

systemd-cgls 指令给 cgroup 层级提供了静态数据快照。要查看按资源使用量(CPU、内存和 IO)排序的、正在运行的 cgroup 动态描述请使用:

systemd-cgtop
# systemd-cgtop 提供的统计数据和控制选项与 top 实用工具所提供的相近
┌──[root@liruilongs.github.io]-[~]
└─$ systemd-cgtop

在这里插入图片描述

第 4 章 控制群组应用示例

4.1. 定义数据库 I/O 的优先级

在数据库服务器专用的虚拟机内部运行数据库服务器实例,让您可以根据数据库的优先级来为其分配资源。

系统在两个 KVM 虚拟机内部运行两个数据库服务器。一个数据库的优先级较高另一个较低。当两个数据库服务器同时运行,I/O 吞吐量会降低来均等地容纳两个数据库的请求

一旦优先级低的数据库启动(约在时间轴的 45 处),分配给两个服务器的 I/O 吞吐量是相同的。
在这里插入图片描述

为能优先处理来自优先级高的数据库服务器请求,可将此服务器分配给一个 I/O 操作预留量高的 cgroup而优先级低的数据库服务器可以分配给一个 I/O 操作预留量少的 cgroup。可按照以下步骤过程 4.1, “I/O 吞吐量优先化”来完成此操作,这些步骤将全部在主机系统上执行。

4.1.1 I/O 吞吐量优先化

# 请确保两项服务的所用资源统计功能,处于开启状态:
systemctl set-property db1.service BlockIOAccounting=true
systemctl set-property db2.service BlockIOAccounting=true
# 如果将高优先级和低优先级服务的比率设定为 10:1 ,那么在这些服务单位中运行的进程将只能使用可用资源:
systemctl set-property db1.service BlockIOWeight=1000
systemctl set-property db2.service BlockIOWeight=100
显示了优先处理优先级高的数据库请求,而限制优先级低的数据库的情况。一旦数据库服务器移至恰当的 cgroup(约在时间轴的 75 处),I/O 吞吐量就会在两个服务器间按照 10:1 的比率分配。
在这里插入图片描述

4.2. 定义网络流量的优先级

在单一服务器系统中运行多项与网络相关的服务时,定义这些服务的网络优先级是很重要的。定义优先级可以保证源自特定服务的数据包比源自其它服务的数据包享有更高优先级。

例如,当一台服务器系统同时起到 NFS 服务器和 Samba 服务器的作用时,优先级就显得尤为重要。NFS 必须享有高优先权,因为用户会预期较高吞吐量。Samba 的优先级可以较低,以确保 NFS 服务器有更佳表现。

net_prio 管控器可以用来为 cgroup 中的进程设定网络优先级。之后,优先级会被转译为 Type Of Service(TOS,服务类型)比特,并嵌入每一个数据包中。

4.2.1 为共享服务的文件设定网络优先级

  1. net_prio 管控器并未编译进 kernel,它是一个必须手动装载的模块。如需装载,请输入:
modprobe netprio_cgroup
  1. 请将 net_prio 子系统附加到 /cgroup/net_prio cgroup 中:
 mkdir sys/fs/cgroup/net_prio
 mount -t cgroup -o net_prio none sys/fs/cgroup/net_prio
  1. 请为各项服务创建其 cgroup:
mkdir sys/fs/cgroup/net_prio/nfs_high
mkdir sys/fs/cgroup/net_prio/samba_low
  1. 如希望 nfs 服务被自动移至 nfs_high cgroup,请将下列行添至 /etc/sysconfig/nfs 文件:
CGROUP_DAEMON="net_prio:nfs_high"
  1. 此配置可确保 nfs 服务启动或重启时,nfs 服务进程已被移至 nfs_high cgroup

smbd 后台驻留程序在 /etc/sysconfig 目录中没有配置文件。为实现将 smbd 后台驻留程序自动移至 samba_low cgroup,请添加下列行至 /etc/cgrules.conf 文件:

*:smbd                net_prio                samba_low

请注意:此规则会将每一个 smbd 后台驻留程序(不仅仅是 /usr/sbin/smbd)移至 samba_low cgroup

您可以用相似的方式为 nmbd winbindd 后台驻留程序定义规则,将它们移至 samba_low cgroup

  1. 请启动 cgred 服务,以载入之前步骤的配置:Cgred 是​​​一​​​个​​​守​​​护​​​进​​​程​​​,它​​​可​​​根​​​据​​​在​​​ etc/cgrules.conf 文​​​件​​​中​​​设​​​定​​​的​​​参​​​数​​​将​​​任​​​务​​​移​​​动​​​到​​​ cgroup 中​​​。
systemctl start cgred
Starting CGroup Rules Engine Daemon:                       [  OK  ]
  1. 至于此示例的目的,让我们假设两项服务都使用 eth1 网络接口;给每一个 cgroup 定义优先级:1 表示优先级低,10 表示优先级高:
echo "eth1 1" > /sys/fs/cgroup/net_prio/samba_low/net_prio.ifpriomap
echo "eth1 10" > /sys/fs/cgroup/net_prio/nfs_high/net_prio.ifpriomap
  1. 请启动 nfs 和 smb 服务以检查各自的进程是否已被移至正确的 cgroup:
~]# systemctl start smb
Starting SMB services:                                     [  OK  ]
~]# cat /sys/fs/cgroup/net_prio/samba_low/tasks
16122
16124
~]# systemctl start nfs
Starting NFS services:                                     [  OK  ]
Starting NFS quotas:                                       [  OK  ]
Starting NFS mountd:                                       [  OK  ]
Stopping RPC idmapd:                                       [  OK  ]
Starting RPC idmapd:                                       [  OK  ]
Starting NFS daemon:                                       [  OK  ]
~]# cat sys/fs/cgroup/net_prio/nfs_high/tasks
16321
16325
16376

Systemctl 介绍

Systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器。

Systemd是一个系统管理守护进程、工具和库的集合,用于取代System V初始进程。Systemd的功能是用于集中管理和配置类UNIX系统。

在Linux生态系统中,Systemd被部署到了大多数的标准Linux发行版中,只有为数不多的几个发行版尚未部署。

┌──[root@liruilongs.github.io]-[~]
└─$ whereis systemd #检查systemd和systemctl的二进制文件和库的安装位置。
systemd: /usr/lib/systemd /etc/systemd /usr/share/systemd /usr/share/man/man1/systemd.1.gz
┌──[root@liruilongs.github.io]-[~]
└─$ ps -eaf | grep [s]ystemd #检查systemd是否正在运行。
root          1      0  0 18:44 ?        00:00:06 /usr/lib/systemd/systemd --system --deserialize 17
root        438      1  0 18:44 ?        00:00:00 /usr/lib/systemd/systemd-journald
dbus        573      1  0 18:45 ?        00:00:00 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root        585      1  0 18:45 ?        00:00:00 /usr/lib/systemd/systemd-logind
root       1309      1  0 19:17 ?        00:00:00 /usr/lib/systemd/systemd-machined
root       2733      1  0 21:13 ?        00:00:00 /usr/lib/systemd/systemd-udevd
┌──[root@liruilongs.github.io]-[~]
└─$ systemd --version
-bash: systemd: command not found
┌──[root@liruilongs.github.io]-[~]
└─$  systemd-analyze  #分析systemd启动过程
Startup finished in 16.775s (kernel) + 4.983s (initrd) + 28.902s (userspace) = 50.661s
┌──[root@liruilongs.github.io]-[~]
└─$ systemd-analyze blame #分析每个进程在引导时花费的时间
         10.362s docker.service
          5.538s network.service
          3.974s containerd.service
          3.430s etcd.service
          3.421s dev-sda1.device
          2.829s tuned.service
          2.519s postfix.service
          1.730s polkit.service
           710ms auditd.service
           669ms chronyd.service
           641ms rsyslog.service
           565ms sysstat.service
           543ms systemd-vconsole-setup.service
           485ms rhel-dmesg.service
           483ms systemd-tmpfiles-setup-dev.service
           478ms sshd.service
           383ms dev-mqueue.mount
           370ms systemd-remount-fs.service
           368ms sys-kernel-debug.mount
           362ms dev-hugepages.mount
           361ms httpd.service
           342ms rhel-readonly.service
           292ms systemd-journald.service
           229ms systemd-logind.service
           229ms rhel-import-state.service
           182ms plymouth-quit.service
           172ms systemd-udev-trigger.service
           162ms systemd-journal-flush.service
           159ms plymouth-quit-wait.service
┌──[root@liruilongs.github.io]-[~]
└─$ systemd-analyze critical-chain #分析启动时的关键链
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

multi-user.target @28.877s
└─docker.service @18.514s +10.362s
  └─containerd.service @14.536s +3.974s
    └─network.target @14.513s
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-unit-files #列出所有可用的单位
UNIT FILE                                     STATE
proc-sys-fs-binfmt_misc.automount             static
dev-hugepages.mount                           static
dev-mqueue.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
brandbot.path                                 disabled
systemd-ask-password-console.path             static
systemd-ask-password-plymouth.path            static
systemd-ask-password-wall.path                static
session-1.scope                               static
session-11.scope                              static
arp-ethers.service                            disabled
auditd.service                                enabled
autovt@.service                               enabled
blk-availability.service                      disabled
brandbot.service                              static
chrony-dnssrv@.service                        static
chrony-wait.service                           disabled
chronyd.service                               enabled
console-getty.service                         disabled
console-shell.service                         disabled
container-getty@.service                      static
containerd.service                            disabled
cpupower.service                              disabled
crond.service                                 enabled
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-units #列出所有运行单元
UNIT                                            LOAD   ACTIVE SUB       DESCRIPTION
proc-sys-fs-binfmt_misc.automount               loaded active waiting   Arbitrary Executable File Formats File System Au
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda1.device loaded active plugged   VMware_Virtu
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda2.device loaded active plugged   VMware_Virtu
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda.device loaded active plugged   VMware_Virtual_S
sys-devices-pci0000:00-0000:00:11.0-0000:02:00.0-net-ens32.device loaded active plugged   82545EM Gigabit Ethernet Contr
sys-devices-platform-serial8250-tty-ttyS0.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS0
sys-devices-platform-serial8250-tty-ttyS1.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS1
sys-devices-platform-serial8250-tty-ttyS2.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS2
sys-devices-platform-serial8250-tty-ttyS3.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS3
sys-devices-virtual-net-br\x2d4b3da203747c.device loaded active plugged   /sys/devices/virtual/net/br-4b3da203747c
sys-devices-virtual-net-docker0.device          loaded active plugged   /sys/devices/virtual/net/docker0
sys-module-configfs.device                      loaded active plugged   /sys/module/configfs
sys-subsystem-net-devices-br\x2d4b3da203747c.device loaded active plugged   /sys/subsystem/net/devices/br-4b3da203747c
sys-subsystem-net-devices-docker0.device        loaded active plugged   /sys/subsystem/net/devices/docker0
sys-subsystem-net-devices-ens32.device          loaded active plugged   82545EM Gigabit Ethernet Controller (Copper) (PR
-.mount                                         loaded active mounted   /
dev-hugepages.mount                             loaded active mounted   Huge Pages File System
dev-mqueue.mount                                loaded active mounted   POSIX Message Queue File System
run-user-0.mount                                loaded active mounted   /run/user/0
sys-kernel-config.mount                         loaded active mounted   Configuration File System
sys-kernel-debug.mount                          loaded active mounted   Debug File System
brandbot.path                                   loaded active waiting   Flexible branding
systemd-ask-password-plymouth.path              loaded active waiting   Forward Password Requests to Plymouth Directory
systemd-ask-password-wall.path                  loaded active waiting   Forward Password Requests to Wall Directory Watc
session-1.scope                                 loaded active running   Session 1 of user root
session-11.scope                                loaded active running   Session 11 of user root
auditd.service                                  loaded active running   Security Auditing Service
chronyd.service                                 loaded active running   NTP client/server
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl --failed #列出所有失败的单元
0 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl is-enabled crond.service # 检查单元(cron.service)是否启用?
enabled
┌──[root@liruilongs.github.io]-[~]
└─$  systemctl status firewalld.service #检查单元或服务是否正在运
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

使用Systemctl控制和管理服务

┌──[root@liruilongs.github.io]-[~]
└─$  systemctl list-unit-files --type=service  #列出所有服务(包括启用和禁用)
UNIT FILE                                     STATE
arp-ethers.service                            disabled
auditd.service                                enabled
autovt@.service                               enabled
blk-availability.service                      disabled
brandbot.service                              static
chrony-dnssrv@.service                        static
chrony-wait.service                           disabled
chronyd.service                               enabled
console-getty.service                         disabled
console-shell.service                         disabled
container-getty@.service                      static
containerd.service                            disabled
cpupower.service                              disabled
crond.service                                 enabled
dbus-org.freedesktop.hostname1.service        static
dbus-org.freedesktop.import1.service          static
dbus-org.freedesktop.locale1.service          static
dbus-org.freedesktop.login1.service           static
dbus-org.freedesktop.machine1.service         static
dbus-org.freedesktop.timedate1.service        static
dbus.service                                  static
debug-shell.service                           disabled
docker.service                                enabled
dracut-cmdline.service                        static
dracut-initqueue.service                      static
dracut-mount.service                          static
dracut-pre-mount.service                      static
dracut-pre-pivot.service                      static
┌──[root@liruilongs.github.io]-[~]  #在Linux中启动,重新启动,停止,重新加载和检查服务(httpd.service)的状态
└─$ # systemctl start httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl restart httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl stop httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl reload httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl status httpd.service
┌──[root@liruilongs.github.io]-[~]  # 如何在引导时激活服务并启用或禁用服务(系统引导时自动启动服务)
└─$ # systemctl is-active httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl enable httpd.service
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl disable httpd.service
┌──[root@liruilongs.github.io]-[~]  #如何屏蔽(使其无法启动)或取消屏蔽服务(httpd.service)
└─$ ln -s '/dev/null' '/etc/systemd/system/httpd.service'
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl unmask httpd.service
Removed symlink /etc/systemd/system/httpd.service.
┌──[root@liruilongs.github.io]-[~]
└─$ rm '/etc/systemd/system/httpd.service'
rm: cannot remove ‘/etc/systemd/system/httpd.service’: No such file or directory
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl kill httpd  # 如何使用systemctl命令终止服务
┌──[root@liruilongs.github.io]-[~]
└─$ systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/httpd.service.d
           └─50-BlockIOAccounting.conf, 50-CPUShares.conf, 50-MemoryLimit.conf
   Active: failed (Result: exit-code) since Thu 2021-10-14 21:21:12 CST; 6s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 2827 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
 Main PID: 1231 (code=exited, status=0/SUCCESS)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

Oct 13 02:00:13 liruilongs.github.io systemd[1]: Starting The Apache HTTP Server...
Oct 13 02:00:13 liruilongs.github.io systemd[1]: Started The Apache HTTP Server.
Oct 14 21:21:12 liruilongs.github.io kill[2827]: kill: cannot find process ""
Oct 14 21:21:12 liruilongs.github.io systemd[1]: httpd.service: control process exited, code=exited status=1
Oct 14 21:21:12 liruilongs.github.io systemd[1]: Unit httpd.service entered failed state.
Oct 14 21:21:12 liruilongs.github.io systemd[1]: httpd.service failed.
┌──[root@liruilongs.github.io]-[~]
└─$ cat /etc/systemd/system/httpd.service
cat: /etc/systemd/system/httpd.service: No such file or directory

使用Systemctl控制和管理挂载点

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-unit-files --type=mount
UNIT FILE                     STATE
dev-hugepages.mount           static
dev-mqueue.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

7 unit files listed.
┌──[root@liruilongs.github.io]-[~]  # .如何装载,卸载,重新装载,重新装载系统装载点,以及检查系统上装载点的状态
└─$ # systemctl start tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl stop tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl restart tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl reload tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl status tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl is-active tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl enable tmp.mount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl disable  tmp.mount

使用Systemctl控制和管理套接字

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-unit-files --type=socket
UNIT FILE                    STATE
dbus.socket                  static
docker.socket                disabled
sshd.socket                  disabled
syslog.socket                static
systemd-initctl.socket       static
systemd-journald.socket      static
systemd-shutdownd.socket     static
systemd-udevd-control.socket static
systemd-udevd-kernel.socket  static

9 unit files listed.
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl start cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl restart cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl stop cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl reload cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl status cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl is-active cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl enable cups.socket
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl disable cups.socket

 服务的CPU利用率(份额)

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl show -p CPUShares httpd.service
CPUShares=600
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl set-property httpd.service CPUShares=2000
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl show -p CPUShares httpd.service

检查服务的所有配置详细信息

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl show httpd
Type=notify
Restart=no
NotifyAccess=main
RestartUSec=100ms
TimeoutStartUSec=1min 30s
TimeoutStopUSec=1min 30s
WatchdogUSec=0
WatchdogTimestampMonotonic=0
StartLimitInterval=10000000
StartLimitBurst=5
StartLimitAction=none
FailureAction=none
PermissionsStartOnly=no
RootDirectoryStartOnly=no
RemainAfterExit=no
GuessMainPID=yes
MainPID=0
ControlPID=0
FileDescriptorStoreMax=0
StatusText=Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec
StatusErrno=0
Result=exit-code
ExecMainStartTimestamp=Wed 2021-10-13 02:00:13 CST
ExecMainStartTimestampMonotonic=421085770
ExecMainExitTimestamp=Thu 2021-10-14 21:21:12 CST
ExecMainExitTimestampMonotonic=9398280544
ExecMainPID=1231
ExecMainCode=1
ExecMainStatus=0

分析服务的关键链(httpd)

┌──[root@liruilongs.github.io]-[~]
└─$ systemd-analyze critical-chain httpd.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

httpd.service +361ms
└─network.target @14.513s

获取服务的依赖项列表(httpd)

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl list-dependencies httpd.service
httpd.service
● ├─-.mount
● ├─system.slice
● └─basic.target
●   ├─microcode.service
●   ├─rhel-autorelabel-mark.service
●   ├─rhel-autorelabel.service
●   ├─rhel-configure.service
●   ├─rhel-dmesg.service
●   ├─rhel-loadmodules.service
●   ├─selinux-policy-migrate-local-changes@targeted.service
●   ├─paths.target
●   ├─slices.target
●   │ ├─-.slice
●   │ └─system.slice
●   ├─sockets.target
●   │ ├─dbus.socket
●   │ ├─systemd-initctl.socket
●   │ ├─systemd-journald.socket
●   │ ├─systemd-shutdownd.socket
●   │ ├─systemd-udevd-control.socket
●   │ └─systemd-udevd-kernel.socket
●   ├─sysinit.target
●   │ ├─dev-hugepages.mount
●   │ ├─dev-mqueue.mount
●   │ ├─kmod-static-nodes.service
●   │ ├─plymouth-read-write.service
●   │ ├─plymouth-start.service
●   │ ├─proc-sys-fs-binfmt_misc.automount
┌──[root@liruilongs.github.io]-[~]
└─$ # systemd-cgls
┌──[root@liruilongs.github.io]-[~]
└─$ # systemd-cgtop
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl rescue #启动系统救援模式
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl emergency #进入紧急模式

列出当前使用的运行级别

┌──[root@liruilongs.github.io]-[~]
└─$ systemctl get-default
multi-user.target
┌──[root@liruilongs.github.io]-[~] # 启动Runlevel 5 aka图形模式。
└─$ # systemctl isolate runlevel5.target
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl isolate graphical.target
┌──[root@liruilongs.github.io]-[~] #启动Runlevel 3又称多用户模式(命令行)
└─$ # systemctl isolate runlevel3.target
┌──[root@liruilongs.github.io]-[~]  #将多用户模式或图形模式设置为默认运行级别
└─$ # systemctl set-default runlevel3.target
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl set-default runlevel5.target

控制系统运行级别

┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl reboot
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl halt
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl suspend
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl hibernate
┌──[root@liruilongs.github.io]-[~]
└─$ # systemctl hybrid-sleep
┌──[root@liruilongs.github.io]-[~]
└─$
相关文章
|
1月前
|
Ubuntu Linux Python
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
在Linux系统中,使用Tkinter库时可能会遇到中文显示乱码的问题,这通常是由于字体支持问题导致的,可以通过更换支持中文的字体来解决。
126 0
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
|
3月前
|
Linux
Linux源码阅读笔记10-进程NICE案例分析2
Linux源码阅读笔记10-进程NICE案例分析2
|
3月前
|
Linux
Linux源码阅读笔记09-进程NICE案例分析1
Linux源码阅读笔记09-进程NICE案例分析1
|
1月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
83 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
Unix Linux 开发工具
linux笔记 diff及patch的制作与使用
这篇文章是关于Linux系统中使用`diff`命令生成补丁文件以及使用`patch`命令应用这些补丁的详细教程和实战案例。
90 2
linux笔记 diff及patch的制作与使用
|
3月前
|
安全 Linux 开发者
Linux笔记之ldd命令详解
`ldd`命令是Linux环境下一个非常实用的工具,用于显示一个程序运行时所需的共享库依赖。它帮助开发者和系统管理员快速诊断程序运行问题,特别是在处理"找不到库文件"或者"错误的库文件版本"等错误时。然而,出于安全的考虑,对于不信任的可执行文件,应该慎用 `ldd`命令,可以考虑使用其他工具如 `objdump`。总的来说,懂得如何妥善且安全地使用 `ldd`,对于维护一个稳定和高效的Linux系统来说,是非常重要的。
72 9
|
3月前
|
Linux
Linux源码阅读笔记13-进程通信组件中
Linux源码阅读笔记13-进程通信组件中
|
3月前
|
消息中间件 安全 Java
Linux源码阅读笔记13-进程通信组件上
Linux源码阅读笔记13-进程通信组件上
|
3月前
|
存储 缓存 编译器
Linux源码阅读笔记06-RCU机制和内存优化屏障
Linux源码阅读笔记06-RCU机制和内存优化屏障
|
3月前
|
Linux 开发者
Linux源码阅读笔记18-插入模型及删除模块操作
Linux源码阅读笔记18-插入模型及删除模块操作