systemd-cgroups
理想情况下,一个service有一个与之对应的进程。应当能清晰查找,但实际情况有些不同。一个service可能使用了多个进程,且对于守护进程,它可以生成任意第三方进程, 这会使得service的进程管理实际变得困难。即很难通过 ps
命令只看看明白。尽管可以使用ps xajf
查看进程继承数,但仍有问题,如父进程退出的进程,其父进程PID 会被重定向到init进程;如果一个进程fork了两次,那么最最后的就会直接失去与初始进程的联系(这对于守护进程是很常见的)。
以上这些原因,就导致难以界定一个service中到底有哪些进程。为此,systemd使用cgroups来管理service。
systemd 将生成的每个进程放入以其服务命名的控制组中,cgroups
可以按层次结构排列和标记进程。当服务中的进程生成子进程时,这些子进程自动成为父进程cgroup 的成员,无论fork多少次,没有特权的进程是无法离开cgroup的。使用cgroup技术,就可以确保fork出的进程无法脱离服务名的标签;而且还可以安全的kill一个服务及它创建 的所有相关进程。
有两个命令可以查看 进程和其cgroup的关系。
1
2
3
$ ps xawf -eo pid,user,cgroup,args
## 或
$ systemd-cgls
可以使用 systemd-cgls
,这个命令通过它们的cgroup和service来显示进程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ systemd-cgls
Control group /:
-.slice
├─1944 bpfilter_umh
├─user.slice
│ ├─user-1001.slice
...
│ │ ├─user@1001.service
│ │ │ ├─gsd-xsettings.service
│ │ │ │ └─3884408 /usr/libexec/gsd-xsettings
│ │ │ ├─gvfs-goa-volume-monitor.service
│ │ │ │ └─3884351 /usr/libexec/gvfs-goa-volume-monitor
│ │ │ ├─gsd-power.service
│ │ │ │ └─3884386 /usr/libexec/gsd-power
│ │ │ ├─xdg-permission-store.service
│ │ │ │ └─3884261 /usr/libexec/xdg-permission-store
│ │ │ ├─xdg-document-portal.service
│ │ │ │ └─3884615 /usr/libexec/xdg-document-portal
│ │ │ ├─xdg-desktop-portal.service
│ │ │ │ └─3884718 /usr/libexec/xdg-desktop-portal
│ │ │ ├─gsd-sound.service
│ │ │ │ └─3884399 /usr/libexec/gsd-sound
│ │ │ ├─gsd-rfkill.service
│ │ │ │ └─3884390 /usr/libexec/gsd-rfkill
│ │ │ ├─gsd-usb-protection.service
│ │ │ │ └─3884400 /usr/libexec/gsd-usb-protection
│ │ │ ├─gsd-print-notifications.service
│ │ │ │ ├─3884388 /usr/libexec/gsd-print-notifications
│ │ │ │ └─3884455 /usr/libexec/gsd-printer
│ │ │ ├─evolution-calendar-factory.service
│ │ │ │ └─3884283 /usr/libexec/evolution-calendar-factory
│ │ │ ├─gsd-a11y-settings.service
│ │ │ │ └─3884378 /usr/libexec/gsd-a11y-settings