案例现象
今天早上打开虚拟机终端,发现一直有进程往我的 1.txt 文件里写东西,删除之后又重新生成
而且 1.txt 大小已经五百多M了
使用 top 命令查看一下,发现用户态cpu使用率已经达到百分之 60,而且都是 bash 进程在占用 cpu资源
定位问题
依稀记得我在前一天晚上执行了一些命令,如下
while true; do sleep 1 && (time echo hello) >> 1.txt 2>&1; done &
这条命令意思是每间隔一秒,将 time echo hello 输出的内容重定向到 1.txt 文件中,& 是放在后台执行的意思
然后使用 history 工具查看一下历史命令,发现我昨晚敲了不止一条!
一般来讲我们后台执行的进程可以通过 jobs 命令来查看
但是我敲 jobs 没有任何输出,这是为什么呢?
原来 jobs 命令只能查看当前终端后台运行命令 ,如果终端关闭之后再重新打开是无法看到的
由于我昨晚关闭了终端,所以今天重新打开终端敲 jobs 命令没有显示
解决问题
既然知道了是我昨晚敲的命令放在了后台执行且没有及时kill掉
导致这些后台进程一直往我的文件里写东西,消耗了大量的资源
那么我只需要将这些后台进程全部kill掉就行
使用 ps 命令查看一下相关进程
ps -ef | grep 1.txt
发现没有任何输出,我们过滤其他字段看看
[root@localhost ~]# ps -ef | grep bash
root 51387 51357 0 15:58 pts/0 00:00:00 -bash
root 51391 51357 0 15:58 pts/0 00:00:00 -bash
root 51395 51357 0 15:58 pts/0 00:00:00 -bash
root 51401 51357 0 15:58 pts/0 00:00:00 -bash
root 51357 51353 0 15:58 pts/0 00:00:00 -bash
root 52191 51451 0 15:58 pts/0 00:00:00 grep --color=auto bash
发现有多个 bash 进程,我们知道,这些 bash 进程里面除了有上面敲的bash命令产生的后台进程,还有一个就是 bash 父进程
我们知道,shell 提供了用户与系统内核进行交互的一种接口,它能够接收用户输入的命令并把它们送到内核去执行,简单来讲 shell 就是一个命令解释器
在 linux 系统里有许多 shell,默认的都是 bash(Bourne Again shell),我们每开启一个终端时就会创建一个 bash 父进程,这个 bash 父进程负责把我们在终端输入的命令传送到内核,让我们能够与内核进行交互
你接下来执行的命令都是这个 bash 进程的子进程,因为它是大部分命令行启动的程序的父进程
所以说我们不能够将过滤出的 bash 进程全部 kill 掉,因为其中就有一个是 bash 父进程
我们知道,打开终端后敲的 bash 命令都是由 bash 父进程 fork 出一个个子进程去执行的,既然是父子关系,我们可以使用 pstree 工具来查看
pstree
pstree 命令是用于查看进程树之间的关系,即哪个进程是父进程,哪个是子进程
我列出几个比较常用的参数:
-A:各进程树之间的连接以ASCII码字符来连接
-U:各进程树之间的连接以utf8字符来连接,某些终端可能会有错误
-p:同时列出每个进程的PID
-u:同时列出每个进程的所属账号名称
我们执行pstree命令来查看一下进程树
pstree -p
我们可以看到有两个 bash 父进程(因为我打开了两个终端)在第一个 bash 父进程(51357)下创建了多个子 bash,而每一个子 bash 创建了一个 sleep 进程去执行相关命令
但我们发现这些 sleep 进程的 PID 一直在变化,进程的 PID 在变化,一般有以下两个原因:
-
进程运行时间比较短,也就是在其他应用内部通过 exec 调用的外面命令
-
进程在不停地崩溃重启,比如因为段错误、配置错误等等
既然 sleep 进程是由子 bash 进程创建的,我们可以将子 bash 进程给温柔的 kill 掉
kill 51387
kill 51391
...
kill 掉之后我们重新过滤下 bash 进程
ps -ef | grep bash
root 51357 51353 0 16:10 pts/0 00:00:00 -bash
root 52191 51451 0 16:10 pts/0 00:00:00 grep --color=auto bash
发现执行命令的子 bash 进程已经全部 kill 掉
我们再删除 1.txt,看看还有没有进程写入导致文件重新生成
rm -rf 1.txt
发现1.txt 没有再自动生成,成功解决问题!