Linux Shell编程几则

2012真是不安稳,才放假回来线上服务就各种问题==# 好一点的直接出core,还算有的调试。还有直接莫名其妙Hang住的,而且之前设计的运行监控在这个关键时刻也失灵了。为了保证服务进程运行正常,我们自己写了一套进程监控脚本,当服务异常时会报警或是重启服务。经过检查发现正是这个监控脚本的问题,记录在此。

在Shell中获取制定进程的CPU和内存占用量

对进程监控主要的监控指标就那么几个:cpu,内存,运行状态等等。手工查看的很容易,可以直接使用所有Linux发行版都带的Top工具和PS工具,或是使用自己装的更专业的Sar之类的管理工具。直接运行top会默认进入一个不断刷新的curse屏幕,上边按照一定的规则动态显示系统中全部进程的信息,其中就包括PID,优先级,虚拟内存占用量,实际内存占用率,CUP占用率等等,输出的字段也是可以自定义的。

默认的Top输出是一个curse界面,这对人类是友好的,但是却不利于Shell脚本处理。我们可以使用-b参数让内容直接输出到stdout上,同样还是每隔一段时间更新一次。如果只想要一次输出,可以进一步加上-n 1参数。为了查看指定PID进程的信息,则可以再加上-p PID参数。同时配合grep和awk等工具即可取得想要的PID进程的某个字段信息。比如要看PID=1的全字段信息:

sagi@sagi-desktop:~$ top -b -n 1 -p 1 | grep root  
    1 root      20   0  2792 1720 1228 S    0  0.1   0:00.34 init

要取得PID=1的进程的CPU占用率,可以这样:

sagi@sagi-desktop:~$ top -b -n 1 -p 1 | grep root | awk '{print $9}'  
0  

同样利用PS工具同样可以轻松完成。直接执行ps显示的信息很少,因为默认只显示和当前终端相关的进程。可以使用-ef参数显示全部进程信息。不过ps默认并不显示进程资源占用情况,这就需要使用-o选项自定义输出字段。比如要显示pid,ppid,cpu占用率,虚拟内存使用量,实际内存使用量可以使用这样写:

sagi@sagi-desktop:~$ ps -o pid,ppid,pcpu,vsz,rss  
  PID  PPID %CPU    VSZ   RSS
 2172  2171  0.0   6576  3732
 2411  2172  0.0   2504   840

如果想要显示指定PID的内容可以加上–pid=PID参数。另外上边输出中的标题栏多少有些不利于Shell中处理,可以再加上h选项,这样就不会输出标题栏了。另外PS比Top方便的一点是,可以使用-C appname选项查看指定名字的进程,不一定要用PID。

另外不管是TOP还是PS亦或是其它管理工具,都是从/proc/文件系统中获取到的系统信息,如果所有的工具都不能满足需求,完全可以自己读取/proc中的内容自己写一个。

Top和PS显示的CPU占用率不一致!

这次的BUG就是出现在这里,脚本中用的是PS查看某个服务进程的CPU占用率,当发现实际占用率超过阈值时则触发报警。结果实际情况是在TOP中发现进程的CPU使用率已经超过100%了,而PS中显示的只有45%左右。通过查看man文档发现如下:

CPU usage is currently expressed as the percentage of time spent running during the entire lifetime of a process. This is not ideal, and it does not conform to the standards that ps otherwise conforms to. CPU usage is unlikely to add up to exactly 100%. %cpu %CPU cpu utilization of the process in "##.#" format. Currently, it is the CPU time used divided by the time the process has been running (cputime/realtime ratio), expressed as a percentage. It will not add up to 100% unless you are lucky. (alias pcpu).

原来PS中显示的CPU占用率是从程序启动开始计时的平均值。而TOP的man文档中为:

k: %CPU  --  CPU usage  
          The  task's  share  of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.  In a true SMP environment, if 'Irix mode' is Off, top will operate in 'Solaris mode' where a task's cpu usage will be divided by the total  number  of  CPUs.   You toggle 'Irix/Solaris' modes with the 'I' interactive command.

可以看到TOP显示的CPU占用率是从上一次屏幕刷新开始计算的值。所以要查看当前进程的CPU利用率,应该以TOP的值为准。如何从TOP中读出进程的CPU利用率上一节中已经说明。

Shell中的浮点计算

Bash对浮点的计算的支持并不好。如果是整数的比较可以使用-lt -gt -eq分别表示小于,大于,等于。如果是字符串则可以直接使用<,>,=。如果操作数是浮点数就不能这样比较了。好在Unix的KISS原则,是的Unix/Linux中有非常多的功能单一,但是可以灵活组合的小工具。bc通常都是作为计算器用,这里我们利用bc来比较两个浮点数:

sagi@sagi-desktop:~$ echo "10.5 > 6.7" | bc  
1  
sagi@sagi-desktop:~$ echo "10.5 < 6.7" | bc  
0  

可以看到当条件满足时,返回的是1,反之返回为0。所以在条件判断中可以如下写:

if [ $(echo "10.5 > 6.7" | bc) -eq 1 ]; then  
   echo "OK"
fi  

当然还有别的方法来比较浮点数,比如使用sed将浮点数中的小数点后边去掉,进而转换成整数再比较等等。

comments powered by Disqus