Linux系统资源监控脚本

本文涉及一些在Linux系统中进行资源监控的方法,其目的是为了在实际工作中监控系统的资源使用情况。

问题提出

自上个月开始,断断续续排查了几个疑难 bug,都是在生产环境发现的,兹事体大,必须解决,但限于能力和环境,有的bug并没有即时解决,但总算在一定期限内完成任务,由于时间紧,当时并没有详细记录过程,但过后回想,还是要做些经验总结。本文从进程占用内存脚本开始,对 Linux 资源使用情况的监控展开研究,以方便日后使用。

监控CPU和内存占用最多的十个进程

Linux 系统一般使用 ps 命令查看进程资源使用情况,其输出结果如下:

1
2
3
4
5
$ ps aux | head -n 4
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.1 191136 4172 ? Ss 14:51 0:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0.0 0.0 0 0 ? S 14:51 0:00 [kthreadd]
root 3 0.1 0.0 0 0 ? S 14:51 0:02 [ksoftirqd/0]

从输出结果可以看出有CPU、内存、进程ID、进程名称等信息,其中CPU和内存的数值为百分比。

由此可知核心命令描述如下:

通过 ps 命令查看进程CPU、内存占用情况,再分别按CPU、内存数值倒序排序,再取前面10个即可。

查看内存占用最多的十个进程命令如下:

1
ps aux | grep -v PID | sort -rn -k +4 | head -n10

解释:

  • grep -v PID 为去掉带 PID 字样的一行,此处表示标题。
  • sort -rn -k +4,-k +4 表示按第4列(即内存)内容排序,-rn 表示按数值倒序排序。
  • head -n10表示取前面的10个,亦即占用内存最多的10个进程。

类似地,对于CPU占用情况,只需要将上面+4改为+3即可,因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
#!/bin/bash

PROCESS=foobar
LOGFILE="memlog.txt"

#!/bin/bash
# for ((;;))
# while [ 1 ]
while :
do
PID=$(ps aux | grep $PROCESS | grep -v 'grep' | awk '{print $2;}')
if [ "$PID" != "" ]; then
echo `date +'%Y-%m-%d %H:%M:%S'` >> "$LOGFILE"
MEM=$(ps aux | grep $PROCESS | grep -v 'grep' | awk '{print $5;}')
MEM="ps mem: "$MEM
RSS=$(cat /proc/$PID/status | grep RSS)
echo $PROCESS $MEM $RSS >> "$LOGFILE"
fi

echo "System memory info: " $(cat /proc/meminfo | grep -E 'MemTotal|MemFree|Cached' |grep -v SwapCached|xargs) >> "$LOGFILE"
echo "-------------" >> "$LOGFILE"

sleep 5
done

注释如下:

  • 由于要监控某一进程,因此需先指定进程名称。
  • 再从 ps 列表中查询其 PID 和 内存
  • 再由 PID 查询其常驻内存大小,该值在/proc/<PID>/status文件中。

脚本每隔5秒输出一次信息,有时内存泄漏量较小,一般观察数小时、半天可以得到结果。确定存在内存泄漏情况时,再深入代码排查。该脚本对占用内存大小并不做严格计算,因为只是观察内存使用是否稳定,或是否持续增长,是否有跳变。就当时监控情况下,该进程下载文件时内存占用突增,过后恢复稳定状态,但保持几分钟十多KB增长的态势,因此判定内存泄漏。

判断磁盘占用情况

本脚本用于磁盘空间使用情况的监控。机制如下:

指定监控目录,指定空间使用百分比的阈值,当超过时,再删除。根据经验,一般超过 85%~90%时即可删除。该脚本可使用定时任务执行,根据磁盘使用空间,可半天或一天执行一次。

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
37
38
39
40
41
42
43
44
45
46
47
48
#!/bin/sh

#前提:已挂载目录
mount_dir=/mnt/hgfs
percent_in=85
file_del=1000

count_del=10

# 如果不存在目录,退出
if [ ! -d $mount_dir ]; then
echo $mount_dir "not found, quit"
exit
fi

percent=`df -h | grep $mount_dir | awk '{print $5}' | tr -d '%'`
dev_file=`df -h | grep $mount_dir | awk '{print $1}'`
file_count=`ls -l $mount_dir | wc -l`

echo $percent $percent_in
# 当空间占用百分比大于某个指定值时,删除目录前指定的数量
if [ $percent -ge $percent_in ];then
echo "need to remove file! occupy" $percent"%" "of" $dev_file
#cd $mount_dir
#file=`ls | sort | head -$file_del`
#rm $file
#cd -
else
echo "no need to remove file"
fi

# 按文件数量判断,用于文件体积小但数量大的情况,因其会占用文件索引
#if [ $file_count -ge $count_del ];then
# echo "need to remove file! occupy total" $count_del "files of" $dev_file
#cd $mount_dir
#file=`ls | sort | head -$file_del`
#rm $file
#cd -
#else
# echo "no need to remove file"
#fi

#file=`ls | sort | head -$file_del`
#echo $file

echo "comand complete at"
date
echo "======================================"

进阶

可在脚本中添加邮件通知功能(可用其它程序实现),当出现异常或有重大事件发生时——如CPU占用达100%或删除文件时,不过目前暂未有时间着手。