linux CPU资源高、内存高分析(网络收集)

目录

例:列举出一小时内占用的cpu最多的10个进程
例:linux下获取占用CPU/内存资源最多的10个进程
例:获取java最耗cpu资源线程信息
例:CentOS下找出占用CPU资源最多的线程
例:aix系统上最耗内存的前10个进程
例:LINUX类主机JAVA应用程序占用CPU、内存过高分析手段

例:检测最耗cpu的线程的脚本

 

 

列举出一小时内占用的cpu最多的10个进程

CPU是一种很重要的资源,如果能够跟踪某个阶段内占用的CPU最多的进程,通过监视一段时间内的CPU使用情况,我们可以找出长期占用CPU的进程并对其进行优化,提高CPU使用效率,我们知道ps指令适用于收集进程详细信息,接下来我们就来通过使用ps指令来监视并计算一分钟内CPU使用情况,shell代码如下:

#!/bin/bash

SECS=60
UNIT_TIME=5

STEPS=$(( $SECS / $UNIT_TIME ))
echo Watching CPU usage...;
for((i=0;i<STEPS;i++))
do
ps -eo comm,pcpu | tail -n +2 >> /tmp/cpu_usage.$$
sleep $UNIT_TIME
done

echo
echo CPU eaters:
cat /tmp/cpu_usage.$$ | \
awk '
{ process[$1] += $2; }
END{
for(i in process)
{
printf("%-20s%s\n",i,process[i]);
}
}' | sort -nrk 2 | head
rm /tmp/cpu_usage.$$

 

 测试结果:

CPU eaters:
glance-registry     321.5
glance-api          246.5
polkitd             63.6
dbus-daemon         34.8
console-kit-dae     32.4
su                  23
NetworkManager      18
ksoftirqd/0         14.4
init                14.4
kworker/0:0         8

2. 列出网络上所有的活动主机

#!/bin/bash

for ip in 192.168.123.{1..255};
do
    (
        ping $ip -c2 &> /dev/null;
        if [ $? -eq 0 ];
        then
        echo $ip is alive
        fi
    )&
done
wait

测试结果:

192.168.123.22 is alive
192.168.123.16 is alive
192.168.123.26 is alive
192.168.123.28 is alive
192.168.123.30 is alive
192.168.123.31 is alive
192.168.123.33 is alive
192.168.123.41 is alive
192.168.123.43 is alive
192.168.123.46 is alive
192.168.123.47 is alive
192.168.123.44 is alive
192.168.123.49 is alive
192.168.123.50 is alive
192.168.123.54 is alive
192.168.123.55 is alive
192.168.123.56 is alive
192.168.123.59 is alive
192.168.123.57 is alive
192.168.123.58 is alive
192.168.123.62 is alive
192.168.123.64 is alive
192.168.123.65 is alive
192.168.123.66 is alive
192.168.123.67 is alive
192.168.123.71 is alive

linux下获取占用CPU/内存资源最多的10个进程

 

ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=%cpu
这个命令实际调试程序的时候非常有用,列出了进程id, 线程id和cpu占有率,同时按照cpu占有率排序。

1、linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合:

ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head  

2、linux下获取占用内存资源最多的10个进程,可以使用如下命令组合:

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


命令组合解析(针对CPU的,MEN也同样道理): ps aux
|head -1;ps aux|grep -v PID|sort -rn -k +3|head 该命令组合实际上是下面两句命令: ps aux|head -1 ps aux|grep -v PID|sort -rn -k +3|head 其中第一句主要是为了获取标题内容(即USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND这些内容),接下来的grep -v PID是将ps aux获得的结果去掉上面的标题,即grep不包含PID这三个字母组合的行,再将其中结果使用sort排序,sort -rn -k +3该命令中的-rn的r表示是结果倒序排列,n为以数值大小排序,而-k +3则是针对第3列的内容进行比对排序,再使用head命令获取默认前10行数据。(其中的|表示管道操作)

 

获取java最耗cpu资源线程信息

n=$1
if [ -z $n  ];
then
    n=1
fi
pid=`jps -lv|grep Server|awk '{print $1}'`
ps H -eo pid,ppid,tid,time,%cpu --sort=%cpu|grep $pid>Thread.txt
jstack  $pid >/wls/wls81/jstack.txt
tid=`tail -n$n Thread.txt |awk {'print $3'}`
cpu=`tail -n$n Thread.txt |awk {'print $5'}`
tid_16=`echo "obase=16;$tid"|bc|tr "[:upper:]" "[:lower:]" `
i=1
for tid_l in $tid_16
do
    echo "tid:$tid_l "
    cpu_l=`echo $cpu|cut -d " " -f $i`
    echo "cpu:$cpu_l"
    task_state=`cat /proc/$pid/task/$tid_l/stat|cut -d " " -f 3`
    echo "task_state:$task_state"                                
    num_threads=`cat /proc/$pid/task/$tid_l/stat|cut -d " " -f 20`
    echo "num_threads:$num_threads"  
    vsize=`cat /proc/$pid/task/$tid_l/stat|cut -d " " -f 23`
    echo "vsize:$vsize" 
    rss=`cat /proc/$pid/task/$tid_l/stat|cut -d " " -f 24`
    echo "rss:$rss" 
    rlim=`cat /proc/$pid/task/$tid_l/stat|cut -d " " -f 25`
    echo "rlim:$rlim" 
    nswap=`cat /proc/$pid/task/$tid_l/stat|cut -d " " -f 36`
    echo "nswap:$nswap" 
    cat jstack.txt|grep 0x$tid_l
    ((i=i+1))

done

 

CentOS下找出占用CPU资源最多的线程

1.对这个进程中的所有线程作监视:top -p pid -H
2.找到最耗CPU的线程:ps -mp pid -o THREAD,tid,time|sort -rn 或者 ps -Lfp pid
3.也可以用下面的命令将 cpu 占用率高的线程找出来:
 ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=%cpu 
这个命令首先指定参数'H',显示线程相关的信息,格式输出中包含:user,pid,ppid,tid,time,%cpu,cmd,然后再用%cpu字段进行排序。这样就可以找到占用处理器的线程了。
直接使用 ps Hh -eo pid,tid,pcpu | sort -nk3 |tail 获取对于的进程号和线程号,然后跳转到3.
查看哪个进程线程占用cpu过高; top / ps -aux, 获得进程号
确定哪个线程占用cpu过高,进入进程号的目录:/proc/pid/task, 
执行:grep SleepAVG  **/status  | sort -k2,2 | head,  确定cpu占用较高的线程号。
使用kill -3 pid 会打印线程堆栈的情况
在 Linux 下 top 工具可以显示 cpu 的平均利用率(user,nice,system,idle,iowait,irq,softirq,etc.),可以显示每个 cpu 的利用率。但是无法显示每个线程的 cpu 利用率情况,这时就可能出现这种情况,总的 cpu 利用率中 user 或 system 很高,但是用进程的 cpu 占用率进行排序时,没有进程的 user 或 system 与之对应。
proc文件系统
/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
/proc目录中有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。此外,在Linux2.6.0-test6以上的版本中/proc/pid目录中有一个task目录,/proc/pid/task目录中也有一些以该进程所拥有的线程的线程号命名的目录/proc/pid/task/tid,它们是读取线程信息的接口。

 

aix系统上最耗内存的前10个进程

 

命令svmon -P -t 10 -i 5的结果被输出到文件svmonresult.txt中,该命令每5秒种输出一次最耗内存的前10个进程。

 

LINUX类主机JAVA应用程序占用CPU、内存过高分析手段

 

 分析CPU占用的方法和手段(使用linux命令查出高CPU使用的进程,分析其是由于进程原因还是系统原因,在分析出为进程消耗过高CPU后列出占用CPU高和占用时间最长的线程并使用jdk自带的jstack工具进行分析CPU使用分析):

  1. top命令:可以查看实时的CPU使用情况。获取java进程占用高的PID13033

  2. ps -ef命令:可以查看进程以及进程中线程的当前CPU使用情况以及属于当前状态的采样数据。第一步:显示线程列表,并按照CPU占用高的线程排序:# ps -mp 13033 -o THREAD,tid,time | sort –rn ;第二步,找到耗时最高的线程ppid,占用CPU时间达8分多钟。将需要的线程ID转换为16进制格式:# printf "%x\n" 28358 ,得到结果6ec6

  3. jstack:Java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。#jstack 13033 | grep 6ec6 -A  30 比对发现占用CPU高服务中高消耗CPU的代码均为一些等待和读取的语句。

  4. pstack:Linux命令。可以查看某个进程的当前线程栈运行情况

 

’jtgrep’是自己随便写的一个shell脚本:

#!/bin/sh
nid=`python -c "print hex($1)" `
grep -i $nid $2

$jstack 13033 > stack.log

$jtgrep 28358 stack.log

 进制转换有多种方式,比如计算器的程序计算器,上述函数等。

 

内存使用分析

在linux的内存分配机制中,系统优先使用物理内存,当物理内存还有空闲,表示还够用时,不会释放其占用内存,即使占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于开启过的程序、或是读取刚存取过得数据会比较快,因此查看目前进程正在实际被使用的内存(used-buffers-cache),也可以认为如果交换分区(swap)没有大量使用,物理内存(mem)还是够用的,只有物理内存(mem)被当前进程实际占用完(没有了buffers和cache),才会使用到交换分区(swap)。

但是从代码的角度,目前研发人员主要关注java.lang.OutOfMemoryError: Java heap space异常,减少不必要的对象创建,同时避免内存泄漏,所以分析代码才是我们接下来要做的主要工作;以下为字符网关分析内存占用的故障排查过程:

● 分析内存性能的方法和技巧:

  1. top命令:可以查看实时的内存使用情况。  

  2. jmap -histo:live [pid],然后分析具体的对象数目和占用内存大小,从而定位代码。

  3. jmap -dump:live,format=b,file=xxx.xxx [pid],然后利用MAT工具分析是否存在内存泄漏等等。

 

检测最耗cpu的线程的脚本

脚本路径:https://github.com/oldratlee/useful-scripts

脚本说明:https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#beer-show-busy-java-threadssh

用于快速排查Java的CPU性能问题(top us值过高),自动查出运行的Java进程中消耗CPU多的线程,并打印出其线程栈,从而确定导致性能问题的方法调用。

用法

show-busy-java-threads.sh
# 从 所有的 Java进程中找出最消耗CPU的线程(缺省5个),打印出其线程栈。

show-busy-java-threads.sh -c

show-busy-java-threads.sh -c -p
# -F选项:执行jstack命令时加上-F选项(强制jstack),一般情况不需要使用
show-busy-java-threads.sh -p -F

show-busy-java-threads.sh -s
# 对于sudo方式的运行,JAVA_HOME环境变量不能传递给root,
# 而root用户往往没有配置JAVA_HOME且不方便配置,
# 显式指定jstack命令的路径就反而显得更方便了

show-busy-java-threads.sh -a
# 记录到文件以方便回溯查看

show-busy-java-threads.sh []
# 多次执行;这2个参数的使用方式类似vmstat命令

##############################
# 注意:
##############################
# 如果Java进程的用户 与 执行脚本的当前用户 不同,则jstack不了这个Java进程。
# 为了能切换到Java进程的用户,需要加sudo来执行,即可以解决:
sudo show-busy-java-threads.sh

# 帮助信息
$ show-busy-java-threads.sh -h
Usage: show-busy-java-threads.sh [OPTION]… [delay [count]]
Find out the highest cpu consumed threads of java, and print the stack of these threads.

Example:
show-busy-java-threads.sh # show busy java threads info
show-busy-java-threads.sh 1 # update every 1 seconds, (stop by eg: CTRL+C)
show-busy-java-threads.sh 3 10 # update every 3 seconds, update 10 times

Options:
-p, –pid find out the highest cpu consumed threads from the specifed java process,
default from all java process.
-c, –count set the thread count to show, default is 5
-a, –append-file specify the file to append output as log
-s, –jstack-path specify the path of jstack command
-F, –force set jstack to force a thread dump(use jstack -F option)
-h, –help display this help and exit
delay the delay between updates in seconds
count the number of updates
delay/count arguments imitates style of vmstat command

 

下边这个脚本用于定位出当前java进程里最耗cpu的那个线程,给出cpu的占用率和当前堆栈信息。

#!/bin/bash

if [ $# -eq 0 ];then
    echo "please enter java pid"
    exit -1
fi

pid=$1
jstack_cmd=""

if [[ $JAVA_HOME != "" ]]; then
    jstack_cmd="$JAVA_HOME/bin/jstack"
else
    r=`which jstack 2>/dev/null`
    if [[ $r != "" ]]; then
        jstack_cmd=$r
    else
        echo "can not find jstack"
        exit -2
    fi
fi

#line=`top -H  -o %CPU -b -n 1  -p $pid | sed '1,/^$/d' | grep -v $pid | awk 'NR==2'`

line=`top -H -b -n 1 -p $pid | sed '1,/^$/d' | sed '1d;/^$/d' | grep -v $pid | sort -nrk9 | head -1`
echo "$line" | awk '{print "tid: "$1," cpu: %"$9}'
tid_0x=`printf "%0x" $(echo "$line" | awk '{print $1}')`
$jstack_cmd $pid | grep $tid_0x -A20 | sed -n '1,/^$/p'

通过这种方式执行

$ bash <(curl -s http://hongjiang.info/busythread.sh) java_pid

 

posted @ 2015-03-04 13:49  milkty  阅读(1604)  评论(0编辑  收藏  举报