很多筒子问我如何能够写出能用的shell脚本

这事其实不难,只要按照以下思路进行就行了

1 把复杂的问题简单化,模块化

2 写出每个模块的伪码

3 组装你的模块

4 写出shell code

5 测试


这事看起来很简单,做起来。。。。。 其实也不难,so easy!

大多数人都是因为害怕所以不敢开始仅次而已,所以筒子们开始吧,从现在开始就动手写你的shell吧

你会喜欢上这工作的!


我们现在就来分析需求统计apache的内存使用量

apache的内存使用量数据如何获得呢?

这事就是硬功夫了,要写shell你得多linux操作系统了解,数据得从/proc/$apachepid/smaps里面获得,对里面的字段进行统计分类来获得。

apache的pid如何获得?

 
    
  1. [root@www conf]# ps -eo user,pid | grep '^apache' 
  2. apache   12160 
  3. apache   12161 
  4. apache   12162 
  5. apache   12163 
  6. apache   12164 
  7. apache   12165 
  8. apache   12166 
  9. apache   12167 

顺着这个思路就可以想到用awk来解决,用awk的数组就可以了

 
    
  1. [root@www conf]# awk ' $3 ~ "kB" { sum[$1] += $2} END {for (key in sum) print key, sum[key]" kB"}' /proc/12160/smaps Shared_Clean: 628 kB Pss: 378 kB Swap: 0 kB Shared_Dirty: 2508 kB Size: 19796 kB Private_Dirty: 152 kB Private_Clean: 0 kB Rss: 3288 kB
  2.  

apache的进程又不是一个,很多个,如何收集所有进程信息呢?

用个循环就可以了,先把apache的pid放到一个数组里面,然后在找个数组里面循环执行awk统计


 
    
  1. APACHEPID=($(ps -eo user,pid | awk '$1~"^apache"{print $2}')) 
  2. #设定数组变量APACHEPID并把获得apache-pid复制给这个数组 
  3. echo "apache total process: ${#APACHEPID[@]}" 
  4. #数组里面元素的个数,就是apache进程的总数 
  5.  
  6.  
  7. for pid in ${APACHEPID[@]} 
  8. do 
  9.     echo $pid: 
  10.     awk ' $3 ~ "kB" { sum[$1] += $2} END {for (key in sum) print key, sum[key]" kB"}'  /proc/$pid/smaps 
  11. done &> /tmp/apachemem 
  12.  
  13. #在数组里面循环执行awk统计,并把结果放入到/tmp/apachemem临时文件内 

最后还可以把这个临时文件输入,如果您愿意,ok,现在这个脚本总体就是这个样子了


 
    
  1. #!/bin/bash 
  2. APACHEPID=($(ps -eo user,pid | awk '$1~"^apache"{print $2}')) 
  3. echo "apache total process: ${#APACHEPID[@]}"    
  4.  
  5.  
  6.  
  7. for pid in ${APACHEPID[@]} 
  8. do 
  9.     echo $pid: 
  10.     awk ' $3 ~ "kB" { sum[$1] += $2} END {for (key in sum) print key, sum[key]" kB"}'  /proc/$pid/smaps 
  11. done &> /tmp/apachemem 
  12.  
  13. echo "apache total memsum:" 
  14. awk '$3 ~ "kB" { sum[$1] += $2} END {for (key in sum) print key, sum[key]" kB"}' /tmp/apachemem 
  15.  
  16. echo "delete tmp file!" 
  17. rm -fr /tmp/apachemem 

怎么样,简单吧!

但是这样的脚本看起来就“很挫”,我们把它变得专业点,也是大家以后养成好的编码习惯,用一种函数编程的思想去写code。


 
    
  1. #!/bin/bash 
  2.  
  3. TMPFILE=/tmp/apachemem 
  4. #get apache pid 
  5. APACHEPID=($(ps -eo user,pid | awk '$1~"^apache"{print $2}')) 
  6. echo "apache total process: ${#APACHEPID[@]}" 
  7.  
  8.  
  9. #define memtotal 
  10. memtotal() { 
  11.     filename=$1 
  12.     awk ' $3 ~ "kB" { sum[$1] += $2} END {for (key in sum) print key, sum[key]" kB"}'  $filename 
  13.  
  14. #get every pid memtotal into tmpfile 
  15. for pid in ${APACHEPID[@]} 
  16. do 
  17.     echo $pid: 
  18.     memtotal /proc/$pid/smaps 
  19.  
  20. done &> $TMPFILE 
  21.  
  22.  
  23. #get apache total memsum 
  24. echo "apache total memsum:" 
  25. memtotal $TMPFILE 
  26.  
  27. #delete tmpfile 
  28. echo "delete tmp file!" 
  29. #rm -fr /tmp/apachemem 

这里把统计的过程设置为一个函数memtotal,这样做的好处是能够提高代码的复用度,看起来也简介,后期修改直接改这个函数就可以了,不用全文修改。

下面是执行的结果


 
    
  1. [root@www tmp]# ./apache-mem.sh  
  2. apache total process: 8 
  3. apache total memsum: 
  4. Shared_Clean: 5024 kB 
  5. Pss: 3024 kB 
  6. Size: 158368 kB 
  7. Shared_Dirty: 20064 kB 
  8. Swap: 0 kB 
  9. Private_Dirty: 1216 kB 
  10. Private_Clean: 0 kB 
  11. Rss: 26304 kB 
  12. delete tmp file! 

时间有限,水平有限,这个脚本还有很多其他需要完善的地方,例如添加交互式的设计,统计哪个服务的内存由参数$1传递进去,脚本的健壮性还有待加强,算是抛砖引玉吧,请大家多交流。

最后想对shell刚入门的筒子说,只要你动手开始写shell就已经成功一半了,剩下的就是一个积累的过程。

加油!!!!你可以的!!!