获取程序占用内存,cpu使用率,服务器ip,程序进程信息并定时生成xml文件
shell脚本初学与linux命令学习
- shell脚本编写
- 需求
- 编写生成各字段要求的值
- 提取本服务器的ip地址信息
- 程序存活1
- 程序cpu使用率0.43
- 程序内存使用率0.5
- 时间戳
- 最近启用时间
- 生成xml脚本
- 配置定时器
- 碰到的异常
- 在执行定时任务的时候,日志中报出 Permission denied 没有权限
- 在修改定时文件后,要重启定时服务
shell脚本编写
由于工作原因,目前遇到一个问题,要求对程序所在服务器进行实时监控,主要监控程序的CPU利用率,程序的内存占用率。刚开始考虑用代码去写,考虑了下,还得java,再结合linux命令,写起来有点麻烦,于是想到了直接用shell编写一个定时脚本。
需求
**文件编码使用utf-8格式编码。文件产生频率为每5分钟产生一个文件,新产生的文件覆盖上一次产生的文件。文件格式为xml文件,格式样例如下: **
编写生成各字段要求的值
#!/bin/bash
#author weixg
#xml文件名
fileName="zhywgl_ywgl_waywgl.xml"
#系统程序名(进程名)
procName="FlowServer"
#版本号
procVersion="1.0"
#最近启用时间
procStartTime=`ps -eo lstart,command| grep -v 'grep'| grep -w $procName | awk '{print($1" "$2" "$3" "$4" "$5);}'`
#程序接收流量速率
inputRate="-1"
#程序输出流量速率
outputRate="-1"
#程序接收日志量大小
inputLog="-1"
#程序输出日志量大小
outputLog="-1"
#统计周期,以分钟为单位
duration="5"
#提取本服务器的ip地址信息
IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`
#服务器用户默认root
psUser=root
#查看进程是否存在
pid=`ps -ef | grep -w $procName | grep -v 'grep' | awk '{print $2;}'`
if [ "$pid" != "" ]; then
ProcAlive=1
else
ProcAlive=0
fi
#cpu使用率
ProcCpu=`ps aux |grep -w $procName | grep -v 'grep'| awk '{print($3);}'`
#程序内存使用率
ProcMem=`ps aux |grep -w $procName | grep -v 'grep'| awk '{print($4);}'`
#时间戳
Timestamp=`date +%s`
echo "fileName is $fileName"
echo "procName is $procName"
echo "procVersion is $procVersion"
echo "inputRate is $inputRate"
echo "outputRate is $outputRate"
echo "inputLog is $inputLog"
echo "outputLog is $outputLog"
echo "duration is $duration"
echo "pid is $pid"
echo "ProcAlive is $ProcAlive"
echo "ProcCpu is $ProcCpu"
echo "ProcMem is $ProcMem"
echo "IP is $IP"
echo "procStartTime is $procStartTime"
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
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255
inet6 fe80::5054:ff:fe68:1c8a prefixlen 64 scopeid 0x20<link>
ether 52:54:00:68:1c:8a txqueuelen 1000 (Ethernet)
RX packets 13295352 bytes 3943242853 (3.6 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 12367502 bytes 2298562223 (2.1 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 2898759 bytes 338158163 (322.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2898759 bytes 338158163 (322.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
/sbin/ifconfig -a|grep inet 过滤筛选出inet的值
inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255
inet6 fe80::5054:ff:fe68:1c8a prefixlen 64 scopeid 0x20<link>
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1从上一步过滤去掉(反匹配)值为127.0.0.1的信息
inet 172.16.0.3 netmask 255.255.240.0 broadcast 172.16.15.255
inet6 fe80::5054:ff:fe68:1c8a prefixlen 64 scopeid 0x20<link>
inet6 ::1 prefixlen 128 scopeid 0x10<host>
/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6 同上一步的作用一样
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}’ 输出第二位的值
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值
172.16.0.3
程序存活1</ ProcAlive >
#查看进程是否存在
pid=`ps -ef | grep -w $procName | grep -v 'grep' | awk '{print $2;}'`
if [ "$pid" != "" ]; then
ProcAlive=1
else
ProcAlive=0
fi
$procName是变量名
ps -ef | grep -w $procName
查询出进程
ps -ef | grep FlowServer
root 5596 15476 0 17:10 pts/1 00:00:00 grep --color=auto FlowServer
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’
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;} 输出字符串第二位
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
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 125492 3696 ? Ss Nov04 3:14 /usr/lib/systemd/systemd -
root 2 0.0 0.0 0 0 ? S Nov04 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S Nov04 0:04 [ksoftirqd/0]
root 31207 0.0 15.1 3591284 587332 ? Sl Nov13 7:05 java -jar /home/java/FlowS
ps aux |grep -w $procName 过滤进程名的信息
root 8478 0.0 0.0 112708 1004 pts/1 S+ 17:25 0:00 grep --color=auto -w FlowServer
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’的数据
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);}’ 输出第四位的数值
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脚本
此编码逻辑是从网上其他大神那里找到的
#! /bin/bash
#author:weixg
#data:20191120
#filename:create_xml.sh
#从外部传入的第一个参数作为xml的文件名
outfile=/var/log/wg/zhywgl_ywgl_waywgl.xml
#xml中的缩进位
tabs=0
# ++++++++++++++++++++++++++++
# 组装一个节点,输出到文件
# 说一说传参数时的这几个区别:假如有下面这个脚本执行的命令
# /path/to/scriptname opt1 opt2 opt3 opt4
# $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
# $# :代表后接的参数『个数』
# $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
# $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
# 在shell中我们可以也可以使用${}包含变量名,来调用变量
# ++++++++++++++++++++++++++++
put_head2(){
echo '<?'${1}'?>' > $outfile
}
put(){
echo '<'${*}'>' >> $outfile
}
# 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
# ${@:2} 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
put_tag(){
echo '<'$1'>'${@:2}'</'$1'>' >> $outfile
}
# 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
put_tag_cdata() {
echo '<'$1'><![CDATA['${@:2}']]></'$1'>' >> $outfile
}
put_head(){
put '?'${1}'?'
}
# 这是一个缩进的算法,自行理解
out_tabs(){
tmp=0
tabsstr=""
while [ $tmp -lt $((tabs)) ]
do
tabsstr=${tabsstr}'\t'
tmp=$((tmp+1))
done
echo -e -n $tabsstr >> $outfile
}
tag_start(){
out_tabs
put $1
tabs=$((tabs+1))
}
tag() {
out_tabs
if [ "$1" == 0 ]
then
put_tag $2 $(echo ${@:3})
elif [ "$1" == 1 ]
then
put_tag_cdata $2 $(echo ${@:3})
fi
}
tag_end(){
tabs=$((tabs-1))
out_tabs
put '/'${1}
}
调用方式如下
此处调用是在上面各字段生成的脚本中调用
source '/home/java/create_xml.sh'
put_head2 'xml version='1.0' encoding="GBK"'
tag_start 'Program'
put_tag 'ProcName' "$procName"
put_tag 'ProcVersion' "$procVersion"
put_tag 'ProcAlive' "$ProcAlive"
put_tag 'ProcStartTime' "$procStartTime"
put_tag 'IP' "$IP"
put_tag 'ProcCpu' "$ProcCpu"
put_tag 'ProcMem' "$ProcMem"
put_tag 'InputRate' "$inputRate"
put_tag 'OutputRate' "$outputRate"
put_tag 'InputLog' "$inputLog"
put_tag 'OutputLog' "$outputLog"
put_tag 'Duration' "$duration"
put_tag 'Timestamp' "$Timestamp"
tag_end 'Program'
echo `date +'%Y-%m-%d %H:%M:%S'`+"执行成功!">>/home/java/shLogs.txt
配置定时器
vi /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
*/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方式
还没有评论,来说两句吧...