Linux系统-服务管理学习笔记

学习基础的Linux的服务与进程管理.

查询已安装的服务

首先了解系统的运行级别:

参考这个: 系统运行级别.

Linux的服务主要分类是这样:

1
2
3
4
5
6
7
8
9
Linux服务
|
|-RPM包默认安装的服务
| |
| |-独立的服务
| |
| |-基于xinetd的服务
|
|-源码包安装的服务

查看系统中的服务可以通过chkconfig --list查看.(非原生服务) 旧指令, 划掉!

应该使用systemctl list-units --type=service来查看.

如果要查看全部的系统的服务,使用systemctl list-unit-files.

这里,我们并不能知道查看到的服务是否在运行当中, 但我们可以从中看出服务的自启动情况.

这些数字和on/off的键值对表明了服务是否是开机自启动的.数字代表的是系统运行状态, 而on/off表示是否自启.

chkconfig命令查询到的是RPM包安装的服务.如要查看源码包安装的服务, 一般是在/usr/local下.
而RPM包一般安装在/etc/init.d/下.

服务启动与端口

一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等.
所以,主机通过”IP+端口”来区分不同的服务的.

常规的服务对应端口可以在/etc/services里查看, 文件很大,有11176行.

既然已经了解端口和服务的关系, 那么查看已经启动的服务的操作就会变成查看端口的操作.

也就是netstat命令.

下面好好说一下这个netstat.

netstat主要用于查看网络后门, 说白了就是看有什么服务在占用端口, 所以也是查看启动服务的命令.

常用的参数有:

1
2
3
4
5
6
-n (numberic~常用) 使用ip和port,而不进行反查.
-a (all) 列出所有连接的状态(tcp/udp/unix socket)
-t (TCP)
-u (UDP)
-p (pid~常用) 列出pid和服务名
-l (listen) 仅列出处于监听状态的服务连接

服务管理

(独立服务.基于xinetd服务) – RPM包

学习服务管理之前, 先知道一些常用的目录, 这些都和RPM包服务有关 列举如下:

1
2
3
4
5
6
7
/etc/init.d/ : 启动脚本的位置
/etc/sysconfig/ : 初始化环境配置文件的位置
/etc : 配置文件的位置
/etc/xineted.conf : xineted的配置文件
/etc/xineted.d/ : 基于xineted服务的启动脚本
/var/lib : 服务产生的数据
/var/log : 日志

查看.启动.终止.重启服务的命令就是 service, 注意, 这只是一直能够便利的方法,(过时方法,划去!) 事实上Linux上应该通过绝对路径来进行启动的, 也就是那个/etc/init.d/

启动.终止.重启服务 使用 systemctl start|stop|restart sth.service

查看服务运行状态使用 systemctl status sth.service

使某个服务开机(不)自启使用 systemctl enable|disable sth.service .

系统管理之ps命令

ps命令是查看当前进程的最常用的命令, 但它提供了BSD命令风格和Linux命令风格的两种语法,也就是pa auxps -le.

ps会输出一大堆东西, 这些东西是什么呢?

1
2
3
4
5
6
7
8
9
10
11
USER : 表示该进程是那个用户产生的
PID : 进程的PID号
%CPU : 该进程占用CPU资源的百分比
%MEM : 该进程占用物理内存的百分比
VSZ : 该进程占用虚拟内存的大小 (KB) -- 虚拟内存集
RSS : 该进程占用实际物理内存的大小 (KB) -- 常驻内存集
TTY : 表示该进程运行在那个终端里 ( tty1-tty表示本地控制台(也就是在腾讯云里进行登录操作的那个窗口.), 其中tty1-tty6是字符终端, tty7是图形终端 pts0-????? 是虚拟终端(也就是XShell.PuTTy这类远程工具的窗口)), 如果是问号 ? ,说明该进程不是用户在终端内启动的, 他们是由内核直接启动的一般认为这样的进程是系统进程.
STAT : 进程的状态 ; 常见的状态有: R (running) 运行, S (sleeping) 睡眠(可中断的), D(sleeping) 不可中断的睡眠, T (stoped) 停止, Z (Zombie) 僵尸进程, s (session leader) 创建者, 负责引导和启动, + 前台进程, < 高优先级, N 低优先级, l 多线程, 克隆线程.
START : 该进程的启动时间
TIME : 该进程占用的CPU运算时间, 不是系统时间
COMMAND : 产生此进程的命令名

ps还有一些可能会用到的命令组合.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--------------
ps -ef
-e 显示所有进程
-f 显示进程启动的详细信息
--------------
ps -ejH
-j 任务控制模式输出
-H 层级结构输出
--------------
ps -eFH
-F 显示完整格式的进程信息
--------------
ps axZ / ps -eM
a 与终端相关的进程
x 与终端无关的进程
Z 显示一列SELinux的数据, 同-M
-M 显示一列SELinux的数据, 同Z
--------------
# 显示某个用户的进程
ps -U/-u root
-U/-u 指明用户
--------------

上面的输出参数是BSD风格的, 现在在补充一些Linux风格:

1
2
3
4
5
NI: nice
PRI: priority, 优先级
PSR: processor, CPU
RTPRIO: 实时优先级
....man

另外一个更方便的命令是pstree命令, 可以以树形结构展示当前进程. 加 -p 参数查看pid号, 同时展开.

系统管理之top命令

top命令是用来检测服务器健康的重要命令, 它的输出也是很多的, 但很多东西都和ps命令相同, 我们来看一下:

top

最上方的状态栏就是top命令的最重要的地方了, 下面的情况基本和ps命令类似, 就不在此记录了.

首先, 最前面的时间是指当前的系统时间, 不是指运行了多长时间, 后面的时间(天数)表示的才是运行的时间, 例如: 这台服务器运行了36分钟.

后一项表示当前登录的用户数, 后面的是平均负载.(1分钟, 5分钟, 15分钟) 平均负载的数字是指等待执行的队列

事实上, 这一行的输出结果和w命令的输出是一样的.

第二行: 分别表示系统中的进程总数以及其中的正在运行的, 睡眠的, 正在停止的, 以及僵尸进程.

第三行的输出是一行很重要的信息, 即CPU的状态, 我们来看一下:

1
2
3
4
5
6
7
8
%Cpu(s): 用户模式占用的CPU百分比 默认直接显示总数情况
sy : 系统模式占用
ni : 改变过优先级的用户进程占用
id : 空闲CPU的百分比 (重要)
wa : 等待IO的进程 (重要)
hi: 硬件中断
si: 软件中断 (进行用户空间和内核空间的切换)
st: 偷走的 (虚拟化技术)

使用t命令进行显示视图的切换, 使用l命令来进行uptime信息的显示和隐藏.

下面的是内存占用情况, 没有搞清楚, 暂时空缺. 等到搞清楚Linux的内存模型再补上.

在进入top的界面后, 我们会发现数据是实时刷新的, 在这个交互界面中我们可以进行排序:

1
2
3
P: 以占据的CPU百分比
M: 占据内存的百分比
T: 累计占据的CPU的时长

默认的刷新时间是3.0s, 我们可以在交互式的界面里使用s来进行调整.

使用m可以改变内存占用情况的视图, 使用1命令来对CPU进行挨个查看.

另外, 在启动时可以直接使用-d #来指定刷新时间. 如果在调用的时候使用了-n参数, 在后面跟上数字表示刷新几次之后直接退出.

然而, top已经很有历史了, 现在我们使用一个更强的进程管理程序:

htop

看起来就比top更厉害吧! 还有一些很强大的功能. 下面简单列举一下:

首先..我不明白这个东西为什么要支持鼠标点击…

使用<F5>或者t来进行树形视图和列表视图的切换,

使用p来进行路径全名的展示/缩略

H/K分别用来进行显示/隐藏用户进程和内核进程

斜线反斜线用来进行进程和过滤器的搜索和设定, 过滤器是动态过滤的, 很赞.

使用空格进行多选, 后序可以直接进行批量的kill操作, 使用k

如果说你有多个CPU核心, 那么你可以将某个进程绑定到某个具体的CPU上. 使用a.

htop最强的的两个功能来了, 对特定进程使用s可以进行追踪这个进程进行了什么系统调用. 并且支持即时滚动

第二个就是打开文件描述符, 尽管你可以通过打开/proc下的fd文件夹进行查看, 但是既然这个都封装了一层, 为什么不直接用呢 在相应的进程上使用l即可打开, 这个比直接打开fd可以看到更多信息哦.(比如说你不仅会看到打开的文件, 还可以查看到加载仅内存的库有哪些, 以及他们的文件类型, 以及大小)

杀死进程

结束进程的命令有这几个 kill,killall,pkill, 这些命令的作用都是类似的, 区别在于有些可以杀死单一进程, 有些可以杀死多进程, 接下来一个一个说.

Linux杀死进程通过信号来执行. kill -l来查看所有的信号 (64个)

signals

其中常用的是1.2.9.15这些.

信号 信号名称 信号说明
1 SIGHUP 让进程立即关闭, 然后重新读取配置文件重启(平滑重启), 举个例子就是说:正在使用服务器的用户不会被踢掉, 但是配置会重新加载
2 SIGINT 程序终止信号相当于是ctrl+c, (INTERRUPT)
9 SIGKILL 立即结束程序的运行, 这个信号不会被阻塞.处理.忽略, 一般用于强制结束终止进程
15 SIGTERM 正常结束进程的信号, 是kill的默认信号, 如果进程发生问题, 这个信号会失去作用, 这个时候再考虑信号9

使用kill杀死一个进程就像这样, kill -9(signal) 15936(pid), 但要注意, 直接使用-9造成的影响和你rm -f是一样的,所以一定要小心.

在指定信号时, 支持多种方法:

  • 信号的数字标识: 1 2 9
  • 信号的完整名称: SIGHUP
  • 信号的简写名称: HUP

另外, 向Apache这样的进程会有一运行就会有10几个进程, 而kill一次只能干掉一个,于是在这种情况下我们就可以使用killall.

1
killall -i -9 httpd

其中, -i参数表示interactive, 会不断询问你是否要杀死某个进程.

最后再想象这样的场景; 你使用last命令,发现有人同时登陆了terminal,然后你很坏, 想把他踢了, 这个时候你想到了杀死他的登陆进程, 可是, 看的不是很清楚, 你害怕把自己给踢掉了.

这个时候怎么办呢? 此时就是使用pkill的时候了.

pkill可以添加-t参数, 来指定TTY名, 这样就方便多了. 你先使用w命令, 非常快速的辨认出对方的TTY(因为在同一时间使用w的概率太低了), 接着你优雅的敲下了 pkill -9 -t pts/1.

有一个和pkill同组的命令叫pgrep. 从名字就可以看出, grep是用来做筛选的, 那么pgrep就是用来进行进程筛选的.

常用的选项有:

1
2
3
4
5
6
-u uid: 有效用户所指
-U uid: 真实用户
-t terminal 与指定终端相关的进程
-l 显示进程名
-a 显示完整格式的进程名
-P pid: 显示其父进程为此处指定的进程的进程列表

有一个快速从进程名获得其所有的pid的命令: pidof , 还有一个专门用来先查看进程状态的命令: pidstat.

修改进程的优先级

又到了使用ps的时候了, 但是注意, 如果要查看进程的优先级, 就不能使用ps aux了, 此时就要使用ps -le了.

样例输出如下:

优先级

其中的PRI表示priority, NI表示Nice, 这两个值都是优先级, 越小表示优先级越高.

最终生效的是PRI这个优先级, 而且用户不能修改PRI的值(即使是root也不能), 用户仅可以修改NI的值.

最终系统计算的优先级是PRI+NI的值.

而在修改NI的时候有注意事项:

PRI的默认值为80
NI的值的范围是-20 - 19 (对于root而言)
而普通用户只能将其改为0-19, 而且只能调整自己的进程.

这就意味, root用户才能提高进程的优先级.

另外, nice仅仅可以修改新执行的命令的优先级, 用法类似这样: nice -n -5 tar -zvxf node-v6.10.2.tar.gz.

这样,运行的tar就会以75PRI执行.

如果要改变一个已经启动的进程的优先级的话, 就要使用renice命令.

使用的效果就像是这样:

renice.

最后说一句:

进程的优先级调整被用户发现的几率几乎为0, 优先级的调整更多是在嵌入式开发的上面. 所以,如果你不信仰玄学, 就不要随意修改优先级了.

工作管理

工作管理指的是在单个登录终端中,同时管理多个工作的行为.

简单地说,就是放入后台.

想想在Windows下,放入后台其实就是指最小化, 那么为什么要最小化或者说放入后台呢?

很简单, 窗口挡着我们工作或者进行其他事了. 在Linux下类比就是占着终端了.

举个很简单的例子: make或者make install. 在执行完这个命令后,你是不是就被堵住了..?

但是工作也不能滥用:

  • 首先,放在后台的工作要是能运行一段时间的, 比如ls/pwd这种, 你放在后台没有任何意义, 因为他们很快就执行完了.
    • 此外,后台的工作为了能够一直持续运行, 他不能与用户交互, 比如:vim, 把它放在后台同样没有意义, 因为它相当于是暂停了.

如何将一个命令放在后台工作呢?

有两种方法: 一个是在命令的末尾添加 & 号(命令继续运行), 一个是在命令执行的过程中按下 ctrl+z.(会使得命令暂停)

接下来, 你就可以通过 jobs -l 来查看放入后台的工作和他们的PID号了.

来看这么一种情况:

jobs-top

这两个top使用不同的方法进入后台, 一个是ctrl+z, 一个是&, 可是神奇的是, 两个都是stopped的状态 ?

补充: 看到+号-号了吗? 这个表明放入后台的次序, “+”号表明最近放入后台的工作, 而”-“表示倒数第二个, 恢复工作时会默认恢复”+”号也就是最近一个.

原因很简单, 因为top命令的功能是将信息展示给前台, 并且提供与用户的交互(需要用户的介入). 放到后台就会直接停止.

那么如何将放在后台的工作放回到前台呢?

有这样的一组命令:

1
2
bg %n 放到后台 (将后台的Stopped的工作变为Running)
fg %n 放到前台 (将后台的工作拉回到前台).

这里的n是指工作号 , 也就是[ ]里面的数字.

脱离终端

假使,当我们在一个终端使用了top命令, 在另一个终端中我们使用ps aux就会看到这个进程, 那么,当第一个终端退出时, 这个top也将会被终止掉, 原因是因为终端在退出时, 会结束掉自己所有的进程(发送SIGHUP信号(?)), 但这并不是我们想要的, 如果这是数据库进程, 我们当然不希望它会伴随的终端的退出而结束, 所以, 这就需要脱离终端.

Linux提供三种方法:

  • 把要后台执行的命令加入到/etc/rc.local中
  • 使用系统定时任务(下面会有)
  • 使用nohup命令(标准方法)

nohup是最常用的一种.

查询系统资源

1.vmstat

这个命令整合了进程,内存,交换分区,磁盘IO,系统,CPU负载情况.

vmstat [刷新延时 刷新次数] 这样的格式和top是很像的. 如果仅指定第一个参数, 那么vmstat将会一直输出下去.

例如:vmstat 1 3

vmstat

这里有很多信息在之前的PS和TOP中都见过呢, 但仍然出现了一些没有见过的, 来说一下:

  • procs: 进程信息字段
  • -r : 等待运行的进程数 ( ready? )
  • -b : 不可被唤醒的进程数量 ( 被阻塞(block)的进程 )
  • io: 磁盘读写的信息字段
  • b 表示block 块设备和系统的读入和写入, io的单位是kb
  • system : 系统信息字段
  • in: 每秒被打断的的进程次数 (interrupt)
  • cs: 每秒进行的进程(上下文)切换次数 (switch)

除了直接进行简单的表查看, 可以在vmstat 的后面加上-s来显示内存的统计数据.

vmstat也是一个很有年头的工具了, 一个更好用功能更强大的是dstat.

2.dstat

dstat支持很多信息的显示, 包括电池电量等等 并且 dstat支持插件机制, 这意味着dstat可以统计很多你原先想象不到的内容, 比如统计MySQL的连接 数据IO, NFS的各种状态, 无线网络的信号的强度, 邮件发送的队列情况等等.

在dstat后面加上数字表示的信息和以往不同. 这个数字表示dstat显示累积的间隔数据, 说人话就是显示出来的信息是这X秒的summary.

1
2
3
4
5
6
7
8
9
10
-C 显示CPU信息 0, 3(哪一颗), total(所有的)
-D total, sda(会列出单独的磁盘信息)
-r 显示IO请求的统计数据
-s 显示swapped相关的统计数据
--ipc 进程间通信: 消息队列 信号量 共享内存
--tcp
--udp
--unix
--raw
--socket

不加参数时, dstat会默认加上-cdngy == -a, 也就是输出: Cpu, Disk, Net, paGing, sYstem.

dstat还有一个很强的功能, 那就是显示当前系统的最占用的进程是什么:

1
2
3
4
[root@WWW ~]$ dstat --top-cpu 最占用CPU的
[root@WWW ~]$ dstat --top-mem 最占用内存的
[root@WWW ~]$ dstat --top-io 最占用IO的进程
[root@WWW ~]$ dstat --top-lantency 延迟最大的进程

3.dmesg

这个命令可以查看开机信息.

4.free

查看内存使用状态.

在后面加: [-b|-k|-m|-g] 可以以不同的单位显示.(默认是-k)

这里要注意, free命令显示出的used不全是程序占用的, 其中还有buffer/cache占用的, 所以真实的内存占用应该是free+buffer+cache.

5.lsof

列出进程打开或使用的文件信息.

  • 文件名 查询这个文件被什么进程调用
  • -c (char?)字符串 仅列出以字符串开头的文件
  • -u (user)用户名 只列出以某个用户的进程打开的文件
  • -p (pid)PID 列出某个进程打开的文件

这个命令的输出内容是很多的. 最好加上less或者more

6.pmap

pmap可以显示进程占用的页实际的物理地址以及其他一些信息

使用方法很简单, 直接在后面跟上进程的PID就好了. 选项几乎很少使用, 也就是一个-x用来显示详细格式的信息.

其实这个命令底层调用的文件就是/proc/$PID/maps这个文件. 所以另外一种实现就是直接cat这个文件

7.glances

glances是一个使用python实现的借由python-psutil库实现的一个系统监视工具,基于C/S架构, 可以通过套接字连接到其他的主机上来监视主机状态.

简单的看一下说明就可以上手了, 指令设计都很相像

可以将结果输出成HTML格式的文档, 使用-o参数来指定文件类型{HTML,CSV} 首先要指定输出的文件夹: -f <folder>

8.其他

  • file /bin/ls 来判断系统位数
  • uname 略
  • lsb_release CentOS7 已经没有了
  • uptime 查看运行时间 用户数 平均负载(w/top的第一行)
  • cat /proc/cpuinfo 查看CPU的信息
  • cat /proc/meminfo

缓冲和缓存的区别

简单来说, 缓存(cache)是用来加速数据从硬盘中读取的, 而缓冲(buffer)是用来加速数据”写入”硬盘的.

定时任务

使用at来进行闹钟任务{我自己命的名 :)}

1
2
3
$ at now +2 minutes # 两分钟后执行
at> ./date.sh >> ./date.log # 执行内容
at> (ctrl+d 保存并退出)

接着可以通过atq查看当前服务器上待执行的任务, 如果要进行删除操作, 执行at.

使用at -c 工作号来查看任务详情.

删除任务使用at -d 等价于atrm

设置时间,格式像这样

1
2
HH:MM
HH:MM YYYY-MM-DD

at还有一些模糊时间支持, 比如:

1
2
noon, midnight, teatime
tomorrow

有一个弱智版的at指令叫batch, 他会让系统自动进行选择执行时间(通常是在系统空闲的时候)

Crontab定时任务请参考这个 :

Crontab学习日志

7.8的补充和更新

再看看/proc/*

现在都知道/proc是直接存在在内存中的, 每一个进程号对应的目录内包含的文件都是内存当中映射出来的.

现在就来好好了解一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/proc/cmdline 加载kernel的时候所执行的参数. 可以知道系统是怎么启动的.
/proc/cpuinfo 本机的CPU参数, 包含频率 类型 和运算功能
/proc/devices 记录了系统的主要设备的设备代号 也就是/dev/下看到的那些主设备号, 和mknod有关
/proc/filesystems 目前系统已经加载的文件系统
/proc/interrupts 当前IRQ的分配状态
/proc/ioports 当前系统上面各个设备的I/O地址
/proc/kcore 内存(RAM)的大小 在64位的系统上表现为128TB, 这个是2的47次方(用户空间的大小)
/proc/loadavg 不需要解释了吧, top/uptime等就是从这里获得的数值
/proc/meminfo 内存使用信息
/proc/modules 当前加载的模块信息, 也可以认为是驱动
/proc/mounts 系统挂载的信息, 你会发现和mount命令是一样的输出
/proc/swaps 系统加载的交换分区的信息
/proc/partition 当前系统的分区情况
/proc/pci 每个PCI总线上面的设备的详细情况.(但不知道为什么,在我的机子上没有这个文件, 但是使用lspci会看到结果, 原来是整合到了/proc/bus/下面了)
/proc/uptime 和使用uptime的输出结果是一致的
/proc/version 内核的版本
/proc/bus/* 一些总线的的设备, 还有USB的设备记录

谁动了我的文件 ?

在一些后台进程出现错误或者当执行某些命令的时候显示device is busy 就要看看到底是什么东西在占用次文件或设备. 如同在Windows下, 删除某些文件时候, 会报正在使用的异常, 此时就需要进行解锁类似.

Linux下查看文件占用的命令有二: fuserlsof

fuser 是通过文件查询正在使用该文件的程序.

1
2
3
4
5
6
7
[root@WWW ~]$ fuser [-umv] [-k [i] [signal]] file
-u 不仅列出进程的PID, 还列出其所有者
-m 将后面的文件名直接上提这个文件系统的最顶层, 对于umount很有效
-v 可以显示具体的命令, 并且会美化格式
-k 在找到之后直接给予SIGKILL
-i 和 -k 配合, 询问是否执行
-signal 默认是9号

现在实际试一次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@WWW ~]$ fuser -uv /etc
# 没有任何显示, 这是因为没有任何进程在使用/etc这个目录, 那/etc下的文件呢?
[root@WWW ~]$ fuser -uvm /etc
USER PID ACCESS COMMAND
/etc: root kernel mount (root)/
root 1 .rce. (root)systemd
...(omitted)
root 578 Frce. (root)auditd
polkitd 597 .rce. (polkitd)polkitd
root 599 .rce. (root)systemd-logind
dbus 605 .rce. (dbus)dbus-daemon
chrony 607 .rce. (chrony)chronyd
root 630 Frce. (root)firewalld
root 631 .rce. (root)crond
root 632 .rce. (root)atd
root 748 .rce. (root)NetworkManager
root 1023 Frce. (root)tuned
root 1025 .rce. (root)sshd
root 1026 Frce. (root)rsyslogd
...(omited)

这些字母代表的权限都是什么意思啊?

c: 此进程在当前的目录下(非子目录)

e: 可被触发成执行状态

f: 是一个被打开的文件

r: 代表顶层目录

F: 该文件被打开了, 不过在等待回应中

m: 可能被分享的动态函数库

另外一个比较常用的就是lsof

lsof是列出进程所打开的文件名

1
2
3
4
5
[root@WWW ~]$ lsof [-aUu] [+d]
-a 多项数据需要同时成立的时候才显示出结果
-U 仅列出Unix like系统的Socket文件类型
-u 后面接username 列出该用户进程所打开的文件
+d 目录文件, 找出某个目录下面的文件

如果什么参数都没有加, 那么默认会输出所有的进程所打开的所有文件, 这样的输出量是可怕的.因此一般都是有目的的来查找的.

示例:

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
[root@WWW ~]$ lsof -u root -a -U
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 12u unix 0xffff88003615e400 0t0 11206 /run/systemd/private
systemd 1 root 20u unix 0xffff8800365c8c00 0t0 11250 /run/lvm/lvmpolld.socket
systemd 1 root 21u unix 0xffff88003615fc00 0t0 11259 /run/systemd/shutdownd
systemd 1 root 22u unix 0xffff8801161ae800 0t0 6804 /run/systemd/notify
systemd 1 root 23u unix 0xffff8801161aec00 0t0 6806 /run/systemd/cgroups-agent
....(omitted)
# 如果这里不加-a参数输出的结果是不一样的哦, 这是因为默认是取并集, -a表示取交集
[root@WWW ~]$ lsof +d /dev
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 0u CHR 1,3 0t0 4788 /dev/null
systemd 1 root 1u CHR 1,3 0t0 4788 /dev/null
systemd 1 root 2u CHR 1,3 0t0 4788 /dev/null
systemd 1 root 28u unix 0xffff8801161adc00 0t0 6829 /dev/log
systemd 1 root 34r CHR 10,235 0t0 6465 /dev/autofs
kdevtmpfs 12 root cwd DIR 0,5 3040 3 /dev
kdevtmpfs 12 root rtd DIR 0,5 3040 3 /dev
systemd-j 473 root 0r CHR 1,3 0t0 4788 /dev/null
systemd-j 473 root 1w CHR 1,3 0t0 4788 /dev/null
systemd-j 473 root 2w CHR 1,3 0t0 4788 /dev/null
systemd-j 473 root 5u unix 0xffff8801161adc00 0t0 6829 /dev/log
systemd-j 473 root 6w CHR 1,11 0t0 4794 /dev/kmsg
systemd-j 473 root 9u CHR 1,11 0t0 4794 /dev/kmsg
lvmetad 488 root 0r CHR 1,3 0t0 4788 /dev/null
systemd-u 504 root 0r CHR 1,3 0t0 4788 /dev/null
auditd 576 root 0u CHR 1,3 0t0 4788 /dev/null
auditd 576 root 1u CHR 1,3 0t0 4788 /dev/null
auditd 576 root 2u CHR 1,3 0t0 4788 /dev/null
dbus-daem 596 dbus 0r CHR 1,3 0t0 4788 /dev/null
systemd-l 605 root 0r CHR 1,3 0t0 4788 /dev/null
systemd-l 605 root 17u CHR 4,6 0t0 4808 /dev/tty6
...(omitted)
# 会发现大量的进程都在使用/dev/null