获取程序占用内存,cpu使用率,服务器ip,程序进程信息并定时生成xml文件

谁借莪1个温暖的怀抱¢ 2023-06-15 09:52 29阅读 0赞

shell脚本初学与linux命令学习

  • shell脚本编写
    • 需求
    • 编写生成各字段要求的值
      • 提取本服务器的ip地址信息
      • 程序存活1
      • 程序cpu使用率0.43
      • 程序内存使用率0.5
      • 时间戳
      • 最近启用时间
    • 生成xml脚本
    • 配置定时器
    • 碰到的异常
      • 在执行定时任务的时候,日志中报出 Permission denied 没有权限
      • 在修改定时文件后,要重启定时服务

shell脚本编写

由于工作原因,目前遇到一个问题,要求对程序所在服务器进行实时监控,主要监控程序的CPU利用率,程序的内存占用率。刚开始考虑用代码去写,考虑了下,还得java,再结合linux命令,写起来有点麻烦,于是想到了直接用shell编写一个定时脚本。

需求

**文件编码使用utf-8格式编码。文件产生频率为每5分钟产生一个文件,新产生的文件覆盖上一次产生的文件。文件格式为xml文件,格式样例如下: **
在这里插入图片描述

编写生成各字段要求的值

  1. #!/bin/bash
  2. #author weixg
  3. #xml文件名
  4. fileName="zhywgl_ywgl_waywgl.xml"
  5. #系统程序名(进程名)
  6. procName="FlowServer"
  7. #版本号
  8. procVersion="1.0"
  9. #最近启用时间
  10. procStartTime=`ps -eo lstart,command| grep -v 'grep'| grep -w $procName | awk '{print($1" "$2" "$3" "$4" "$5);}'`
  11. #程序接收流量速率
  12. inputRate="-1"
  13. #程序输出流量速率
  14. outputRate="-1"
  15. #程序接收日志量大小
  16. inputLog="-1"
  17. #程序输出日志量大小
  18. outputLog="-1"
  19. #统计周期,以分钟为单位
  20. duration="5"
  21. #提取本服务器的ip地址信息
  22. IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`
  23. #服务器用户默认root
  24. psUser=root
  25. #查看进程是否存在
  26. pid=`ps -ef | grep -w $procName | grep -v 'grep' | awk '{print $2;}'`
  27. if [ "$pid" != "" ]; then
  28. ProcAlive=1
  29. else
  30. ProcAlive=0
  31. fi
  32. #cpu使用率
  33. ProcCpu=`ps aux |grep -w $procName | grep -v 'grep'| awk '{print($3);}'`
  34. #程序内存使用率
  35. ProcMem=`ps aux |grep -w $procName | grep -v 'grep'| awk '{print($4);}'`
  36. #时间戳
  37. Timestamp=`date +%s`
  38. echo "fileName is $fileName"
  39. echo "procName is $procName"
  40. echo "procVersion is $procVersion"
  41. echo "inputRate is $inputRate"
  42. echo "outputRate is $outputRate"
  43. echo "inputLog is $inputLog"
  44. echo "outputLog is $outputLog"
  45. echo "duration is $duration"
  46. echo "pid is $pid"
  47. echo "ProcAlive is $ProcAlive"
  48. echo "ProcCpu is $ProcCpu"
  49. echo "ProcMem is $ProcMem"
  50. echo "IP is $IP"
  51. echo "procStartTime is $procStartTime"
  52. echo "Timestamp is $Timestamp"

提取本服务器的ip地址信息

IP=/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"
分析下这个命令:
/sbin/ifconfig -a 查询本机ip

  1. eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  2. inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255
  3. inet6 fe80::5054:ff:fe68:1c8a prefixlen 64 scopeid 0x20<link>
  4. ether 52:54:00:68:1c:8a txqueuelen 1000 (Ethernet)
  5. RX packets 13295352 bytes 3943242853 (3.6 GiB)
  6. RX errors 0 dropped 0 overruns 0 frame 0
  7. TX packets 12367502 bytes 2298562223 (2.1 GiB)
  8. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  9. lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
  10. inet 127.0.0.1 netmask 255.0.0.0
  11. inet6 ::1 prefixlen 128 scopeid 0x10<host>
  12. loop txqueuelen 1000 (Local Loopback)
  13. RX packets 2898759 bytes 338158163 (322.4 MiB)
  14. RX errors 0 dropped 0 overruns 0 frame 0
  15. TX packets 2898759 bytes 338158163 (322.4 MiB)
  16. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

/sbin/ifconfig -a|grep inet 过滤筛选出inet的值

  1. inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255
  2. inet6 fe80::5054:ff:fe68:1c8a prefixlen 64 scopeid 0x20<link>
  3. inet 127.0.0.1 netmask 255.0.0.0
  4. inet6 ::1 prefixlen 128 scopeid 0x10<host>

/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1从上一步过滤去掉(反匹配)值为127.0.0.1的信息

  1. inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255
  2. inet6 fe80::5054:ff:fe68:1c8a prefixlen 64 scopeid 0x20<link>
  3. inet6 ::1 prefixlen 128 scopeid 0x10<host>

/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6 同上一步的作用一样

  1. inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255

/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk ‘{print $2}’ 输出第二位的值

  1. 172.16.0.3

/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk ‘{print $2}’|tr -d “addr:” tr -d 的作用是删除addr字符串,由于没有,所以从上一步还是返回的ip值

  1. 172.16.0.3

程序存活1</ ProcAlive >

#查看进程是否存在

  1. pid=`ps -ef | grep -w $procName | grep -v 'grep' | awk '{print $2;}'`
  2. if [ "$pid" != "" ]; then
  3. ProcAlive=1
  4. else
  5. ProcAlive=0
  6. fi

$procName是变量名
ps -ef | grep -w $procName
查询出进程
ps -ef | grep FlowServer

  1. root 5596 15476 0 17:10 pts/1 00:00:00 grep --color=auto FlowServer
  2. root 31207 1 0 Nov13 ? 00:07:05 java -jar /home/java/FlowServer-1.0.jar

过滤 -v (反匹配) 有 ‘grep’的
ps -ef | grep FlowServer | grep -v ‘grep’

  1. root 31207 1 0 Nov13 ? 00:07:05 java -jar /home/java/FlowServer-1.0.jar

ps -ef | grep -w FlowServer | grep -v ‘grep’ | awk ‘{print $2;} 输出字符串第二位

  1. 31207

补充
算术比较运算符 详情查看[:https://blog.csdn.net/ithomer/article/details/6836382\]
(https://blog.csdn.net/ithomer/article/details/6836382)

-eq 等于 [ 3 -eq $mynum ]
-ne 不等于 [ 3 -ne $mynum ]
-lt 小于 [ 3 -lt $mynum ]
-le 小于或等于 [ 3 -le $mynum ]
-gt 大于 [ 3 -gt $mynum ]
-ge 大于或等于 [ 3 -ge $mynum ]

————————————————

程序cpu使用率0.43

#cpu使用率

ProcCpu=ps aux |grep -w $procName | grep -v 'grep'| awk '{print($3);}'

程序内存使用率0.5

#程序内存使用率

ProcMem=ps aux |grep -w $procName | grep -v 'grep'| awk '{print($4);}'

解析:
ps aux

  1. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  2. root 1 0.0 0.0 125492 3696 ? Ss Nov04 3:14 /usr/lib/systemd/systemd -
  3. root 2 0.0 0.0 0 0 ? S Nov04 0:00 [kthreadd]
  4. root 3 0.0 0.0 0 0 ? S Nov04 0:04 [ksoftirqd/0]
  5. root 31207 0.0 15.1 3591284 587332 ? Sl Nov13 7:05 java -jar /home/java/FlowS

ps aux |grep -w $procName 过滤进程名的信息

  1. root 8478 0.0 0.0 112708 1004 pts/1 S+ 17:25 0:00 grep --color=auto -w FlowServer
  2. root 31207 0.0 15.1 3591284 587332 ? Sl Nov13 7:05 java -jar /home/java/FlowServer-1.0.jar

ps aux |grep -w $procName | grep -v ‘grep’ 过滤取出含有‘grep’的数据

  1. root 31207 0.0 15.1 3591284 587332 ? Sl Nov13 7:05 java -jar /home/java/FlowServer-1.0.jar

ps aux |grep -w $procName | grep -v ‘grep’| awk ‘{print($4);}’ 输出第四位的数值

  1. 15.1

时间戳

Timestamp=date +%s 当前时间 格式为时间戳

时间命令:date

向date命令传递参数适用‘+‘(加号),在传递的参数中

%Y表示年

%m表示月

%d表示天

%H表示小时(表示的时间是00-23)

%M表示分钟

%S表示秒

%s(表示unix时间戳的秒数)

1.1例如 date +%Y-%m-%d

这个在我的机器上面的结果是:

在这里插入图片描述
date命令的输出结果是对当前时间的以传递的参数进行格式化

1.2例如date +’%Y-%m-%d %H:%M:%S’
在这里插入图片描述

1.3获取当前时间的unix时间戳

date +%s

在这里插入图片描述

1.4使用date命令获取一个特定时间的unix时间戳

在这里插入图片描述

最近启用时间

procStartTime=ps -eo lstart,command| grep -v 'grep'| grep -w $procName | awk '{print($1" "$2" "$3" "$4" "$5);}'

生成xml脚本

此编码逻辑是从网上其他大神那里找到的

  1. #! /bin/bash
  2. #author:weixg
  3. #data:20191120
  4. #filename:create_xml.sh
  5. #从外部传入的第一个参数作为xml的文件名
  6. outfile=/var/log/wg/zhywgl_ywgl_waywgl.xml
  7. #xml中的缩进位
  8. tabs=0
  9. # ++++++++++++++++++++++++++++
  10. # 组装一个节点,输出到文件
  11. # 说一说传参数时的这几个区别:假如有下面这个脚本执行的命令
  12. # /path/to/scriptname opt1 opt2 opt3 opt4
  13. # $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
  14. # $# :代表后接的参数『个数』
  15. # $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
  16. # $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
  17. # 在shell中我们可以也可以使用${}包含变量名,来调用变量
  18. # ++++++++++++++++++++++++++++
  19. put_head2(){
  20. echo '<?'${1}'?>' > $outfile
  21. }
  22. put(){
  23. echo '<'${*}'>' >> $outfile
  24. }
  25. # 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
  26. # ${@:2} 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
  27. put_tag(){
  28. echo '<'$1'>'${@:2}'</'$1'>' >> $outfile
  29. }
  30. # 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
  31. put_tag_cdata() {
  32. echo '<'$1'><![CDATA['${@:2}']]></'$1'>' >> $outfile
  33. }
  34. put_head(){
  35. put '?'${1}'?'
  36. }
  37. # 这是一个缩进的算法,自行理解
  38. out_tabs(){
  39. tmp=0
  40. tabsstr=""
  41. while [ $tmp -lt $((tabs)) ]
  42. do
  43. tabsstr=${tabsstr}'\t'
  44. tmp=$((tmp+1))
  45. done
  46. echo -e -n $tabsstr >> $outfile
  47. }
  48. tag_start(){
  49. out_tabs
  50. put $1
  51. tabs=$((tabs+1))
  52. }
  53. tag() {
  54. out_tabs
  55. if [ "$1" == 0 ]
  56. then
  57. put_tag $2 $(echo ${@:3})
  58. elif [ "$1" == 1 ]
  59. then
  60. put_tag_cdata $2 $(echo ${@:3})
  61. fi
  62. }
  63. tag_end(){
  64. tabs=$((tabs-1))
  65. out_tabs
  66. put '/'${1}
  67. }

调用方式如下

此处调用是在上面各字段生成的脚本中调用

  1. source '/home/java/create_xml.sh'
  2. put_head2 'xml version='1.0' encoding="GBK"'
  3. tag_start 'Program'
  4. put_tag 'ProcName' "$procName"
  5. put_tag 'ProcVersion' "$procVersion"
  6. put_tag 'ProcAlive' "$ProcAlive"
  7. put_tag 'ProcStartTime' "$procStartTime"
  8. put_tag 'IP' "$IP"
  9. put_tag 'ProcCpu' "$ProcCpu"
  10. put_tag 'ProcMem' "$ProcMem"
  11. put_tag 'InputRate' "$inputRate"
  12. put_tag 'OutputRate' "$outputRate"
  13. put_tag 'InputLog' "$inputLog"
  14. put_tag 'OutputLog' "$outputLog"
  15. put_tag 'Duration' "$duration"
  16. put_tag 'Timestamp' "$Timestamp"
  17. tag_end 'Program'
  18. echo `date +'%Y-%m-%d %H:%M:%S'`+"执行成功!">>/home/java/shLogs.txt

配置定时器

vi /etc/crontab

  1. SHELL=/bin/bash
  2. PATH=/sbin:/bin:/usr/sbin:/usr/bin
  3. MAILTO=root
  4. # For details see man 4 crontabs
  5. # Example of job definition:
  6. # .---------------- minute (0 - 59)
  7. # | .------------- hour (0 - 23)
  8. # | | .---------- day of month (1 - 31)
  9. # | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
  10. # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
  11. # | | | | |
  12. # * * * * * user-name command to be executed
  13. */5 * * * * root /home/java/wangguan.sh 2> /home/java/log 2>&1

*/5 * * * * root /home/java/wangguan.sh 2> /home/java/log 2>&1

解析该命令:

*/5 * * * * :每五分钟执行一次该脚本

root :为用户

/home/java/wangguan.sh :要执行的脚本

2 :表示标准错误,stderr。

: 代表覆盖形式写入

/home/java/log :日志地址

&1 :文件描述符 1,而1标识标准输出,stdout。

2>&1: 将标准错误重定向到标准输出

碰到的异常

在执行定时任务的时候,日志中报出 Permission denied 没有权限

上网查询:
linux中,执行sh显示Permission denied,是由于没有权限的原因,为了获得权限,执行如下命令:

chmod 777 run.sh
其中“run.sh”是我要执行的文件,“chmod 777”是授权语句,“chmod 777 run.sh”的意思是对”run.sh”文件权限进行设置。

在修改定时文件后,要重启定时服务

service crond start
报异常:Redirecting to /bin/systemctl start crond.service

出现Redirecting to /bin/systemctl start crond.service,
即service crond start 需要替换为systemctl方式

发表评论

表情:
评论列表 (有 0 条评论,29人围观)

还没有评论,来说两句吧...

相关阅读