8.6 列出1小时内占用CPU最多的10个进程

CPU时间是一项重要的资源,有时我们需要跟踪某个时期内占用CPU周期最多的进程。在普通的桌面系统或膝上系统中,CPU处于高负荷状态也许不会引发问题。但对于需要处理大量请求的服务器来说,CPU是极其重要的资源。通过监视某个时期内CPU的使用情况,我们可以找出长期占用CPU的进程并对其进行优化,或是调试其他问题。这则攻略是一次有关进程监视与日志记录的实践。

8.6.1 新手上路

ps命令用于收集系统中进程的详细信息。这些信息包括CPU使用情况、正在执行的命令、内存使用、进程状态等。记录在一小时内占用过CPU的进程,然后通过恰当地运用ps以及文本处理就可以找出占用CPU最多的10个进程。关于ps命令的更多细节,请参考第9章。

8.6.2 实战演练

让我们看看用于监视并计算一小时内CPU使用情况的shell脚本:

  1. #!/bin/bash
  2. #文件名: pcpu_usage.sh
  3. #用途:计算1个小时内进程的CPU占用情况
  4. SECS=3600
  5. UNIT_TIME=60
  6. #将SECS更改成需要进行监视的总秒数
  7. #UNIT_TIME是取样的时间间隔,单位是秒
  8. STEPS=$(( $SECS / $UNIT_TIME ))
  9. echo Watching CPU usage... ;
  10. for((i=0;i<STEPS;i++))
  11. do
  12. ps -eo comm,pcpu | tail -n +2 >> /tmp/cpu_usage.$$
  13. sleep $UNIT_TIME
  14. done
  15. echo
  16. echo CPU eaters :
  17. cat /tmp/cpu_usage.$$ | \
  18. awk '
  19. { process[$1]+=$2; }
  20. END{
  21. for(i in process)
  22. {
  23. printf("%-20s %s",i, process[i]);
  24. }
  25. }' | sort -nrk 2 | head
  26. rm /tmp/cpu_usage.$$
  27. #删除临时日志文件

输出如下:

  1. $ ./pcpu_usage.sh
  2. Watching CPU usage...
  3. CPU eaters :
  4. Xorg 20
  5. firefox-bin 15
  6. bash 3
  7. evince 2
  8. pulseaudio 1.0
  9. pcpu.sh 0.3
  10. wpa_supplicant 0
  11. wnck-applet 0
  12. watchdog/0 0
  13. usb-storage 0

8.6.3 工作原理

在上面的脚本中,主要的输入源是ps -eo comm,pcpu,其中comm表示命令名(command name),pcpu表示CPU使用率(CUP usage in percent)。该命令输出所有进程名及CPU使用率。每个进程对应一行输出。因为需要监视一小时内CPU的使用情况,所以我们得在一个每次迭代时间为60秒的for循环中不停地用ps -eo comm,pcpu | tail -n +2来获取CPU的使用统计数据,并将这些数据添加到文件 /tmp/cpu_usage.$$ 中。60秒的迭代时间通过sleep 60来提供。这就使得每一分钟执行一次ps

tail -n +2用来将 ps 输出中的头部和 COMMAND %CPU剥除。

cpu_usage. 中的 表示当前脚本的进程 ID。假设进程 ID为1345,那么在脚本执行时它会被替换成 /tmp/cpu_usage.1345。因为这是一个临时文件,所以我们把它放在 /tmp中。

统计文件在1小时后就准备妥当了,文件中包含了60项,分别对应每分钟的进程状态。然后用awk求出每个进程总的CPU使用情况。我们用了一个关联数组来统计CPU使用情况。其中进程名作为数组索引。最后根据总的CPU使用情况依数值逆序排序,并通过head获得前10项。

8.6.4 参考

  • 4.7节讲解了awk命令。

  • 3.14节讲解了tail命令。