0%

利用ps工具统计CPU/MEM消耗高或者负载高的进程

CPU消耗高往往是系统异常的一种表现。因为平常检查系统运行有哪些进程,都是使用ps工具。因此,出现这种情况时,如果能够通过ps工具搜寻出CPU消耗高的线程,则对进一步搜寻线索或者排查应该有帮助。

一个进程可能包含多个线程。但是考察CPU消耗问题,只考虑进程而不考虑线程是不够的。就是说,我们总是得给ps命令加上“-T”选项。

为了便于按照CPU消耗的情况排序,我们也通过“-o”定制ps输出的字段,以确保CPU消耗占比字段是第一个字段,这样便于排序。

列出消耗高的线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
LANG=C ps -eT -o%cpu,pid,tid,ppid,comm | grep -v CPU | sort -n -r | head -20

#效果如下
[root@es ~]# LANG=C ps -eT -o%cpu,pid,tid,ppid,comm | grep -v CPU | sort -n -r | head -20
26.0 1760 1782 1 java
17.6 1760 22003 1 java
17.0 1760 22006 1 java
16.2 1760 21986 1 java
16.0 1760 22024 1 java
15.0 1760 22025 1 java
14.8 13825 21917 1 java
14.7 13825 21992 1 java
14.2 1760 21989 1 java
14.0 1760 22042 1 java
13.2 13825 21993 1 java
12.6 1760 22008 1 java
12.0 1760 22027 1 java
12.0 13825 22043 1 java
11.0 13825 22047 1 java
10.5 1760 1783 1 java
8.3 13825 22016 1 java
8.0 1760 5966 1 java
8.0 1760 5897 1 java
8.0 13825 14598 1 java

统计线程消耗的总的CPU

1
2
3
4
5
6
7
{ LANG=C ps -eT -o%cpu,pid,tid,ppid,comm | sed -e 's/^ *//' | tr -s ' ' | grep -v CPU | sort -n -r | cut -d ' ' -f 1 | xargs -I{} echo -n "{} + " && echo ' 0'; } | bc -l

#效果如下
[root@es ~]# { LANG=C ps -eT -o%cpu,pid,tid,ppid,comm | sed -e 's/^ *//' | tr -s ' ' | grep -v CPU | sort -n -r | cut -d ' ' -f 1 | xargs -I{} echo -n "{} + " && echo ' 0'; } | bc -l

356.1
[root@es ~]#

应用

设想我们需要追踪CPU占用最高的线程,则可以这样

1
2
3
export LANG=C;d=$(mktemp -d) && cd $d # 建并进入临时目录
# 捕捉之
strace -f -ff -s 256 -tt -T -o strace.log -p $(ps -eT -o%cpu,pid,tid,ppid,comm | grep -v CPU | sort -n -r | head -1 | sed -e 's/^ *//' | tr -s ' ' | cut -d ' ' -f 3)

内存

线程是共享内存空间的。所以,一般情况下,没有必要使用“-T”选项。

列出内存消耗高的进程

1
LANG=C ps -e -o%mem,pid,tid,ppid,comm | grep -v MEM | sort -n -r | head -20

统计内存消耗情况

1
{ LANG=C ps -e -o%mem,pid,tid,ppid,comm | sed -e 's/^ *//' | tr -s ' ' | grep -v MEM | sort -n -r | cut -d ' ' -f 1 | xargs -I{} echo -n "{} + " && echo ' 0'; } | bc -l

列出导致CPU负载高的线程

1
LANG=C ps -eTo stat,pid,tid,ppid,comm,args | perl -ne 'chomp;if (m!^\s*(\S*[RD]+\S*.*)!) {print qq[$1\n];}'

tomcat cpu过高

1,根据top命令,发现PID为2633的Java进程占用CPU高达300%,出现故障。

2,找到该进程后,如何定位具体线程或代码呢,首先显示线程列表,并按照CPU占用高的线程排序

1
2
3
4
5
6
ps -mp 2633 -o THREAD,tid,time | sort -rn

显示结果如下:
USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME
root 10.5 19 - - - - 3626 00:12:48
root 10.1 19 - - - - 3593 00:12:16

找到了耗时最高的线程3626,占用CPU时间有12分钟了!

3.将需要的线程ID转换为16进制格式

1
2
printf "%x\n" 3626
e18

4.最后打印线程的堆栈信息

1
jstack 2633 |grep e18 -A 30