精华内容
下载资源
问答
  • Zabbix在线监控tomcat的线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。...

    Zabbix在线监控tomcat的线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。

    zabbix agent的配置和路径目录结构

    主目录:/etc/zabbix

    自定义脚本目录:/etc/zabbix/custom,里面有如下几个路径:

    conf                         zabbix的配置文件目录

    externalscripts        外部命令脚本

    public                      zabbix公共文件,例如保存的ip和密码

    scripts                     zabbix自定义的脚本

    template                 zabbix模板文件

    自动发现脚本

    这个脚本能够打印出当前服务器上所有的tomcat实例名称,pid进程号和home路径。zabbix会定期执行这个脚本,做到自动发现当前所有的tomcat实例。具体脚本如下:

    # coding: utf-8

    import sys

    import re

    import json

    from optparse import OptionParser

    from qiueer.python.cmds import cmds

    def get_tomcat_list():

    cmdstr = "ps -ef|grep java|grep -v grep|grep \"Dcatalina.home\"|awk '{print $2 ,$(NF-3)}'|sed 's/-Dcatalina.home=//g'"

    c2 = cmds(cmdstr, timeout=3)

    stdo = c2.stdo()

    stde = c2.stde()

    # retcode = c2.code()

    (stdo_list, stde_list) = (re.split("\n", stdo), re.split("\n", stde))

    data = list()

    for tomcat in stdo_list:

    if not tomcat:continue

    data.append({

    "{#TOMCAT_PID}":tomcat.split()[0],

    "{#TOMCAT_PATH}": tomcat.split()[1],

    "{#TOMCAT_NAME}":tomcat.split()[1].split('/')[-1],

    })

    return json.dumps({'data': data}, sort_keys=True, indent=7, separators=(",",":"))

    def main():

    try:

    usage = "usage: %prog [options]\ngGet Tomcat Stat"

    parser = OptionParser(usage)

    parser.add_option("-l", "--list",

    action="store_true", dest="is_list", default=False, help="if list all tomcat")

    (options, args) = parser.parse_args()

    if 1 >= len(sys.argv):

    parser.print_help()

    return

    if options.is_list == True:

    print get_tomcat_list()

    return

    except Exception as e:

    import traceback

    tb = traceback.format_exc()

    print tb

    if __name__ == "__main__":

    main()

    监控脚本

    监控脚本是实际执行jstack的地方,用法如下:

    ./tomcat_thread_status.sh pid username

    pid: tomcat进程号

    username:  运行tomcat的用户名

    脚本:

    #!/bin/bash

    #### 添加sudo权限 ####

    #zabbix ALL=(root) NOPASSWD:/etc/zabbix/custom/scripts/tomcat_thread_status.sh

    #Defaults:zabbix !requiretty

    ####

    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

    tomcat_path=$1

    user=$2

    STATS=(NEW:0 RUNNABLE:0 BLOCKED:0 WAITING:0 TIMED_WAITING:0 TERMINATED:0 TOTAL:0)

    pid=`ps -ef|grep "java .*$tomcat_path"|grep -v grep|awk '{print $2}'`

    if [ $pid ];then

    STATUS=`su - $user -c "jstack $pid|grep -i \"java.lang.Thread.State:\""|awk '{print $2}'|sort|uniq -c|awk '{print $2":"$1}'`

    fi

    if [ ! -z "$STATUS" ];then

    total=0

    for s in $STATUS;do

    key=`echo $s|cut -d: -f1`

    val=`echo $s|cut -d: -f2`

    i=0

    for t in ${STATS[@]};do

    if [ `echo $t|grep -c $key` -eq 1 ];then

    idx=$i

    break

    fi

    let i=$i+1

    done

    STATS[$i]=${key}":"${val}

    let total=$total+${val}

    done

    STATS[6]="TOTAL:"${total}

    fi

    echo ${STATS[@]} | sed -e s/' '/',"'/g -e s/':'/'":'/g -e s/^/'{"thread_status":{"'/g -e s/'$'/'}}'/g

    脚本执行后会返回json格式的字符串,包括new、runnable、blocked等线程状态的数据。

    zabbix agent配置

    UserParameter=custom.tomcat_thread.discovery,python /etc/zabbix/custom/scripts/tomcat_thread_discovery.py --list 2>/dev/null

    UserParameter=custom.tomcat_thread_status.item[*],sudo /etc/zabbix/custom/scripts/tomcat_thread_status.sh "$1" "$2"

    配置单独放在/etc/zabbix/custom/conf里,记得需要在主配置文件/etc/zabbix/zabbix_agentd.conf里include该路径,否则配置不会生效。

    都准备好后重启zabbix agent。

    导入模板配置

    模板配置可以参考这个,下载后导入即可。

    配置主机

    最后在主机的template中添加导入的模板,过会就会发现tomcat已自动发现并添加相关线程的监控。

    写在最后

    具体脚本也可在github上下载:

    自动发现:https://github.com/zhangnq/zabbix/blob/master/scripts/tomcat_thread_discovery.py

    线程监控:https://github.com/zhangnq/zabbix/blob/master/scripts/tomcat_thread_status.sh

    模板:https://github.com/zhangnq/zabbix/blob/master/template/tomcat_thread_status_zbx_v3_template.xml

    配置:https://github.com/zhangnq/zabbix/blob/master/conf/tomcat_thread_status.conf

    项目地址:https://github.com/zhangnq/zabbix

    展开全文
  • 老的方法感觉效果不好,又写了一个模板...Zabbix监控JVM(微服务进程)1、ZabbixServer端配置Zabbix服务器需安装java,编译需添加启动参数--enable-java本次安装的编译参数为:./configure --prefix=/data/zabbix/ --...

    老的方法感觉效果不好,又写了一个模板和脚本,请移步:

    http://www.cnops.top/posts/748ad64f.html

    有兴趣的可以继续往下看。

    Zabbix监控JVM(微服务进程)

    1、ZabbixServer端配置

    Zabbix服务器需安装java,编译需添加启动参数--enable-java

    本次安装的编译参数为:

    ./configure --prefix=/data/zabbix/ --enable-server --enable-agent --with-mysql --enable-ipv6 --with-net-snmp --with-libcurl --with-libxml2 --enable-java

    2、ZabbixAgent端配置

    ZabbixAgent端不仅需要安装zabbix_agentd,还需要安装zabbix_sender,可以通过地址http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/选择合适的版本。

    安装

    rpm -ivh http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-sender-3.0.9-1.el7.x86_64.rpm

    3、监控原理

    微服务的特性:

    1、  每个进程是直接以java-jar service.jar的方式启动,并没有依赖于tomcat或者其他web应用。

    2、  每台服务器上的微服务并没有固定的数量,可以灵活的增加或者减少。

    3、  每个微服务的启动参数已有配置端口很多。

    鉴于此种情况,传统的监控方法监控微服务,会造成经常的手动去增加删减web页面配置,服务器内的端口管理也会很混乱。

    所以使用discovery自动发现的方式去监控微服务。并将每个微服务的信息通过zabbix_sender发送到ZabbixServer端。

    首先java版本为jdk1.8

    # java -version

    java version "1.8.0_161"

    Java(TM) SE Runtime Environment (build 1.8.0_161-b12)

    Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)

    关于微服务的信息主要通过jstat获取,如下

    # ps -ef|grep java

    root 28131 1 0 11:17 ? 00:00:56 java -Xms100M -Xmx500M -Xmn150M -jar /data/work/service_jar/manageMiddle.jar --server.port=20000 --management.port=20001 --config.profile=test

    root 28305 1 0 11:26 ? 00:00:51 java -Xms100M -Xmx300M -Xmn100M -jar /data/work/service_jar/resourceService.jar --server.port=18000 --management.port=18001 --config.profile=test

    root 29067 1 0 11:59 ? 00:00:54 java -Xms100M -Xmx500M -Xmn150M -jar /data/work/service_jar/systemService.jar --server.port=21000 --management.port=21001 --config.profile=test

    root 31345 29980 0 14:03 pts/0 00:00:00 grep --color=auto java

    # jstat -gcutil 28131

    S0 S1 E O M CCS YGC YGCT FGC FGCT GCT

    67.75 0.00 74.28 81.92 97.29 94.90 74 1.248 7 1.065 2.313

    # jstat -gc 28131

    S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT

    14336.0 14848.0 9712.2 0.0 122880.0 91488.9 55808.0 45716.6 56704.0 55169.1 7296.0 6924.1 74 1.248 7 1.065 2.313

    关于输出结果的参数解释

    S0C:年轻代中第一个survivor(幸存区)的容量 (字节)

    S1C:年轻代中第二个survivor(幸存区)的容量 (字节)

    S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)

    S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)

    EC:年轻代中Eden(伊甸园)的容量 (字节)

    EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)

    OC:Old代的容量 (字节)

    OU:Old代目前已使用空间 (字节)

    PC:Perm(持久代)的容量 (字节)

    PU:Perm(持久代)目前已使用空间 (字节)

    YGC:从应用程序启动到采样时年轻代中gc次数

    YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)

    FGC:从应用程序启动到采样时old代(全gc)gc次数

    FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)

    GCT:从应用程序启动到采样时gc用的总时间(s)

    NGCMN:年轻代(young)中初始化(最小)的大小 (字节)

    NGCMX:年轻代(young)的最大容量 (字节)

    NGC:年轻代(young)中当前的容量 (字节)

    OGCMN:old代中初始化(最小)的大小 (字节)

    OGCMX:old代的最大容量 (字节)

    OGC:old代当前新生成的容量 (字节)

    PGCMN:perm代中初始化(最小)的大小 (字节)

    PGCMX:perm代的最大容量 (字节)

    PGC:perm代当前新生成的容量 (字节)

    S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比

    S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比

    E:年轻代中Eden(伊甸园)已使用的占当前容量百分比

    O:old代已使用的占当前容量百分比

    P:perm代已使用的占当前容量百分比

    S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节)

    S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节)

    ECMX:年轻代中Eden(伊甸园)的最大容量 (字节)

    DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满)

    TT: 持有次数限制

    MTT : 最大持有次数限制

    Jdk1.8中取消了永久区Perm

    4、监控脚本

    微服务全部放置在固定的目录内,自动发现微服务脚本为

    # cat java_discovery.py

    #/usr/bin/python

    #This script is used to discovery disk on the server

    import subprocess

    import os

    import socket

    import json

    import glob

    java_names_file='java_names.txt'

    javas=[]

    if os.path.isfile(java_names_file):

    # print 'java_names_file exists!'

    #####

    ##### here should use % (java_names_file) instead of using the python variable java_names_file directly inside the ''' ''' quotes

    #####

    args='''awk -F':' '{print $1':'$2}' %s''' % (java_names_file)

    t=subprocess.Popen(args,shell=True,stdout=subprocess.PIPE).communicate()[0]

    #elif glob.glob('/opt/xx/*_tomcat') and not os.path.isdir('/opt/logs/logstash') and not os.path.isdir('/opt/app/elasticsearch/config'):

    elif glob.glob('/data/work/service_jar/*.jar'):

    t=subprocess.Popen('cd /data/work/service_jar && ls *.jar|grep jar',shell=True,stdout=subprocess.PIPE)

    for java in t.stdout.readlines():

    if len(java) != 0:

    javas.append({'{#JAVA_NAME}':java.strip('\n').strip(':')})

    print json.dumps({'data':javas},indent=4,separators=(',',':'))

    脚本内的目录可以自由修改

    输出结果为json格式

    # python java_discovery.py

    {

    "data":[

    {

    "{#JAVA_NAME}":"insuranceService.jar"

    },

    {

    "{#JAVA_NAME}":"manageMiddle.jar"

    },

    {

    "{#JAVA_NAME}":"resourceService.jar"

    },

    {

    "{#JAVA_NAME}":"systemService.jar"

    }

    ]

    }

    对微服务进行信息获取,并利用zabbix_sender发送的脚本为

    # cat jstat_status.py

    #!/usr/bin/python

    import subprocess

    import sys

    import os

    __maintainer__ = "Francis"

    jps = '/data/jdk1.8/bin/jps'

    jstat = '/data/jdk1.8/bin/jstat'

    zabbix_sender = "/usr/bin/zabbix_sender"

    zabbix_conf = "/etc/zabbix/zabbix_agentd.conf"

    send_to_zabbix = 1

    ip=os.popen("ifconfig|grep 'inet '|grep -v '127.0'|xargs|awk -F '[ :]' '{print $3}'").readline().rstrip()

    serverip="172.19.138.53"

    #"{#JAVA_NAME}":"tomcat_web_1"

    def usage():

    """Display program usage"""

    print "\nUsage : ", sys.argv[0], " java_name alive|all"

    print "Modes : \n\talive : Return pid of running processs\n\tall : Send jstat stats as well"

    sys.exit(1)

    class Jprocess:

    def __init__(self, arg):

    self.pdict = {

    "jpname": arg,

    }

    self.zdict = {

    "Heap_used" : 0,

    "Heap_ratio" : 0,

    "Heap_max" : 0,

    "Perm_used" : 0,

    "Perm_ratio" : 0,

    "Perm_max" : 0,

    "S0_used" : 0,

    "S0_ratio" : 0,

    "S0_max" : 0,

    "S1_used" : 0,

    "S1_ratio" : 0,

    "S1_max" : 0,

    "Eden_used" : 0,

    "Eden_ratio" : 0,

    "Eden_max" : 0,

    "Old_used" : 0,

    "Old_ratio" : 0,

    "Old_max" : 0,

    "YGC" : 0,

    "YGCT" : 0,

    "YGCT_avg" : 0,

    "FGC" : 0,

    "FGCT" : 0,

    "FGCT_avg" : 0,

    "GCT" : 0,

    "GCT_avg" : 0,

    }

    def chk_proc(self):

    # ps -ef|grep java|grep tomcat_web_1|awk '{print $2}'

    # print self.pdict['jpname']

    pidarg = '''ps -ef|grep java|grep %s|grep -v grep | grep -v jstat_status.py |awk '{print $2}' ''' %(self.pdict['jpname'])

    #pidout = subprocess.Popen(pidarg,shell=True,stdout=subprocess.PIPE)

    #pid = pidout.stdout.readline().strip('\n')

    pid = subprocess.check_output(pidarg, shell=True).strip()

    if pid != "" :

    self.pdict['pid'] = pid

    # print "Process found :", java_name, "with pid :", self.pdict['pid']

    else:

    self.pdict['pid'] = ""

    # print "Process not found"

    return self.pdict['pid']

    def get_jstats(self):

    if self.pdict['pid'] == "":

    return False

    self.pdict.update(self.fill_jstats("-gc"))

    self.pdict.update(self.fill_jstats("-gccapacity"))

    self.pdict.update(self.fill_jstats("-gcutil"))

    # print "\nDumping collected stat dictionary\n-----\n", self.pdict, "\n-----\n"

    def fill_jstats(self, opts):

    # print "\nGetting", opts, "stats for process", self.pdict['pid'], "with command : sudo", jstat, opts, self.pdict['pid'] ,"\n"

    # jstatout = subprocess.Popen(['sudo','-u','tomcat', jstat, opts, self.pdict['pid']], stdout=subprocess.PIPE)

    #print([jstat, opts, self.pdict['pid']])

    jstatout = subprocess.Popen([jstat, opts, self.pdict['pid']], stdout=subprocess.PIPE)

    stdout, stderr = jstatout.communicate()

    legend, data = stdout.split('\n',1)

    mydict = dict(zip(legend.split(), data.split()))

    return mydict

    def compute_jstats(self):

    if self.pdict['pid'] == "":

    return False

    self.zdict['S0_used'] = format(float(self.pdict['S0U']) * 1024,'0.2f')

    self.zdict['S0_max'] = format(float(self.pdict['S0C']) * 1024,'0.2f')

    self.zdict['S0_ratio'] = format(float(self.pdict['S0']),'0.2f')

    self.zdict['S1_used'] = format(float(self.pdict['S1U']) * 1024,'0.2f')

    self.zdict['S1_max'] = format(float(self.pdict['S1C']) * 1024,'0.2f')

    self.zdict['S1_ratio'] = format(float(self.pdict['S1']),'0.2f')

    self.zdict['Old_used'] = format(float(self.pdict['OU']) * 1024,'0.2f')

    self.zdict['Old_max'] = format(float(self.pdict['OC']) * 1024,'0.2f')

    self.zdict['Old_ratio'] = format(float(self.pdict['O']),'0.2f')

    self.zdict['Eden_used'] = format(float(self.pdict['EU']) * 1024,'0.2f')

    self.zdict['Eden_max'] = format(float(self.pdict['EC']) * 1024,'0.2f')

    self.zdict['Eden_ratio'] = format(float(self.pdict['E']),'0.2f')

    # self.zdict['Perm_used'] = format(float(self.pdict['PU']) * 1024,'0.2f')

    # self.zdict['Perm_max'] = format(float(self.pdict['PC']) * 1024,'0.2f')

    # self.zdict['Perm_ratio'] = format(float(self.pdict['P']),'0.2f')

    self.zdict['Heap_used'] = format((float(self.pdict['EU']) + float(self.pdict['S0U']) + float(self.pdict['S1U']) + float(self.pdict['OU'])) * 1024,'0.2f')

    self.zdict['Heap_max'] = format((float(self.pdict['EC']) + float(self.pdict['S0C']) + float(self.pdict['S1C']) + float(self.pdict['OC'])) * 1024,'0.2f')

    self.zdict['Heap_ratio'] = format(float(self.zdict['Heap_used']) / float(self.zdict['Heap_max'])*100,'0.2f')

    self.zdict['YGC'] = self.pdict['YGC']

    self.zdict['FGC'] = self.pdict['FGC']

    self.zdict['YGCT'] = format(float(self.pdict['YGCT']),'0.3f')

    self.zdict['FGCT'] = format(float(self.pdict['FGCT']),'0.3f')

    self.zdict['GCT'] = format(float(self.pdict['GCT']),'0.3f')

    if self.pdict['YGC'] == '0':

    self.zdict['YGCT_avg'] = '0'

    else:

    self.zdict['YGCT_avg'] = format(float(self.pdict['YGCT'])/float(self.pdict['YGC']),'0.3f')

    if self.pdict['FGC'] == '0':

    self.zdict['FGCT_avg'] = '0'

    else:

    self.zdict['FGCT_avg'] = format(float(self.pdict['FGCT'])/float(self.pdict['FGC']),'0.3f')

    if self.pdict['YGC'] == '0' and self.pdict['FGC'] == '0':

    self.zdict['GCT_avg'] = '0'

    else:

    self.zdict['GCT_avg'] = format(float(self.pdict['GCT'])/(float(self.pdict['YGC']) + float(self.pdict['FGC'])),'0.3f')

    # print "Dumping zabbix stat dictionary\n-----\n", self.zdict, "\n-----\n"

    def send_to_zabbix(self, metric):

    #### {#JAVA_NAME} tomcat_web_1

    #### UserParameter=java.discovery,/usr/bin/python /opt/app/zabbix/sbin/java_discovery.py

    #### UserParameter=java.discovery_status[*],/opt/app/zabbix/sbin/jstat_status.sh $1 $2 $3 $4

    #### java.discovery_status[tomcat_web_1,Perm_used]

    #### java.discovery_status[{#JAVA_NAME},Perm_used]

    key = "java.discovery_status[" + self.pdict['jpname'] + "," + metric + "]"

    if self.pdict['pid'] != "" and send_to_zabbix > 0:

    #print key + ":" + str(self.zdict[metric])

    try:

    subprocess.call([zabbix_sender, "-c", zabbix_conf, "-k", key, "-o", str(self.zdict[metric])], stdout=FNULL,stderr=FNULL, shell=False)

    except OSError, detail:

    print "Something went wrong while exectuting zabbix_sender : ", detail

    else:

    print "Simulation: the following command would be execucted :\n", zabbix_sender, "-c", zabbix_conf, "-k", key, "-o", self.zdict[metric], "\n"

    accepted_modes = ['alive', 'all']

    if len(sys.argv) == 3 and sys.argv[2] in accepted_modes:

    java_name = sys.argv[1]

    mode = sys.argv[2]

    else:

    usage()

    #Check if process is running / Get PID

    jproc = Jprocess(java_name)

    pid = jproc.chk_proc()

    if pid != "" and mode == 'all':

    jproc.get_jstats()

    #print jproc.zdict

    jproc.compute_jstats()

    FNULL = open(os.devnull, 'w')

    for key in jproc.zdict:

    #print key,jproc.zdict[key]

    jproc.send_to_zabbix(key)

    FNULL.close()

    # print pid

    else:

    print 0

    触发脚本为

    # cat java_discovery_status_sender.py

    #/usr/bin/python

    #This script is used to discovery disk on the server

    import subprocess

    import os

    import socket

    import json

    import glob

    java_names_file='java_names.txt'

    javas=[]

    if os.path.isfile(java_names_file):

    args='''awk -F':' '{print $1':'$2}' %s''' % (java_names_file)

    t=subprocess.Popen(args,shell=True,stdout=subprocess.PIPE).communicate()[0]

    elif glob.glob('/data/work/service_jar/*.jar'):

    t=subprocess.Popen('cd /data/work/service_jar && ls *.jar|grep jar',shell=True,stdout=subprocess.PIPE)

    res=subprocess.check_output('cd /data/work/service_jar && ls *.jar|grep jar',stderr=subprocess.STDOUT,shell = True)

    for java in t.stdout.readlines():

    if len(java) != 0:

    javas.append({'{#JAVA_NAME}':java.strip('\n').strip(':')})

    #print json.dumps({'data':javas},indent=4,separators=(',',':'))

    #print res

    for java in res.strip().split("\n"):

    if java:

    #print java

    out = subprocess.check_output("python /etc/zabbix/scripts/java/jstat_status.py %s all" % java, shell=True)

    #print(out)

    其中web界面配置Host name的参数必须与Agent端配置文件内Hostname的参数完全相同

    将脚本java_discovery_status_sender.py加入crontab

    */1 * * * * root /usr/bin/python /etc/zabbix/scripts/java/java_discovery_status_sender.py

    每分钟触发一次,向server端发信息

    5、userparameter配置

    路径及内容如下

    # pwd

    /etc/zabbix/zabbix_agentd.d

    # cat userparameter_java_discovery_status.conf

    UserParameter=java.discovery,/usr/bin/python /etc/zabbix/scripts/java/java_discovery.py

    UserParameter=java.discovery_status[*],/usr/bin/python /etc/zabbix/scripts/java/jstat_status.py $1 $2

    UserParameter=java.discovery_status_sender,/usr/bin/python /etc/zabbix/scripts/java/java_discovery_status_sender.py

    UserParameter=java.discovery_status[*]和UserParameter=java.discovery_status_sender的作用和原理都是一样的,只不过在Agent端可以执行,在Server端通过zabbix_get调用都会出错,暂时没有找到更好的解决方法。所以通过crontab的方法定时向Server端发送监控信息。如果能够解决问题,或者有更好的解决方法请联系我。

    重启ZabbixAgent端

    6、导入模板

    模板下载地址:https://download..net/download/fjp824/10462387

    导入模板,并将对应的host关联

    可以在Monitoring>Latest data页面根据主机,查看zabbix_trapper接收到的监控信息,如下所以

    66a7397a6fa667cfb96af3b172ee5709.png

    查看图表展示正常,监控完成。

    展开全文
  • 所以想通过zabbix进行多程序状态的监控,一旦这些重要的窗口程序中断,里面产生告警,通知运维人员去修复。提前准备好,两个bat脚本,findexe.bat(把要监控的exe程序做成自动发现),check_exe_status.ba...

    场景模拟:

    国内有部分企业需要运行某些窗口程序(即.exe)来支撑重要的业务运作,一旦这些重要的窗口程序中断了,那么就会造成巨大的经济损失或者影响工作效率,后果如此严重。所以想通过zabbix进行多程序状态的监控,一旦这些重要的窗口程序中断,里面产生告警,通知运维人员去修复。

    提前准备好,两个bat脚本,findexe.bat(把要监控的exe程序做成自动发现),check_exe_status.bat(获取监控exe程序的状态)

    第一步–准备bat脚本:

    findexe.bat脚本的内容如下

    @echo off

    setlocal enabledelayedexpansion

    set /a n=0

    set /a n1=0

    for %%i in (%*) do (set /a n+=1)

    @echo {"data":[

    for %%a in (%*) do (

    set /a n1+=1

    @echo {"{#SERVERNAME}":"%%a"

    if !n1! neq !n! (

    @echo },

    ) else (

    @echo }

    )

    )

    echo ]}

    check_exe_status.bat脚本内容如下

    @echo off

    tasklist|findstr ^%1 >/NUL 2>&1

    if %errorlevel% == 0 (

    echo "running"

    ) else (

    echo "norunning"

    )

    注意tasklist|findstr ^%1 >/NUL 2>&1这条命令是查询监控程序exe有没有运行的

    第二步–制作监控模板

    fdb648e3576dc0818b617d72d48701e8.png

    点击添加,创建模板

    然后在刚才的check_exe_status模板中,创建自动发现规则

    8dd59d6696e9e713b5eab8734dcb8d51.png

    图中键值名为findexe,键值里面的参数就是客户要监控的多个进程,用双引号括起来,中间用空格分割。

    findexe[“firefox.exe chrome.exe xxxlll.exe”]

    如果还有其他exe程序要监控,只需要用空格分割,往后面填入即可。

    接着在这个自动发现规则下,新建一个监控项原型。

    665129c9918e8a3f010ddb567802c758.png

    原型的{#SERVERNAME}的值是固定的有第一步的findexe.bat中定义。

    第三步–配置zabbix_agent.conf的自定义键值

    2bfb274decdc27eca593bc73f5eb033a.png

    脚本路径自定义,自定义键值要和模板的命名一致

    重启zabbix_agent

    第四步–验证多个exe程序状态

    c58387b14fa3f031fb425fc4b2db7d9b.png

    自动发现填入了三个exe程序名,其中xxxll.exe为不存在的exe,为了验证效果,现在把firefox.exe程序关掉,看一下他的最新数据是否会显示成norunning。

    bfab9de93732c381891d7248f382938b.png

    验证成功。

    到此这篇关于Zabbix 结合 bat 脚本实现多个应用程序状态监控的方法的文章就介绍到这了,更多相关Zabbix结合 bat 脚本状态监控内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    展开全文
  • Zabbix本身不支持直接监控Java,在zabbix 1.8以前,只能使用Zapcat来做代理监控,而且要修改源代码,非常麻烦。所有后来为了解决这个监控问题,ZabbixJava双方应运生成了各自的代理监控程序:zabbix 2.0以后添加...

    JAVA-GATEWAY

    Zabbix本身不支持直接监控Java,在zabbix 1.8以前,只能使用Zapcat来做代理监控,而且要修改源代码,非常麻烦。所有后来为了解决这个监控问题,Zabbix和Java双方应运生成了各自的代理监控程序:zabbix 2.0以后添加了服务进程zabbix-java-gateway;Java有了JMX,全称是Java Management Extensions,即Java管理扩展

    技术分享

    比如:当Zabbix-Server需要知道java应用程序的某项性能的时候,会启动自身的一个Zabbix-JavaPollers进程去连接Zabbix-JavaGateway请求数据,而ZabbixJavagateway收到请求后使用“JMXmanagementAPI”去查询特定的应用程序,而前提是应用程序这端在开启时需要“-Dcom.sun.management.jmxremote”参数来开启JMX远程查询就行。Java程序会启动自身的一个简单的小程序端口12345向Zabbix-JavaGateway提供请求数据。


    开始监控部署  

    从上面的原理图中我们可以看出,配置Zabbix监控Java应用程序的关键点在于:配置Zabbix-JavaGateway、让Zabbix-Server能够连接Zabbix-JavaGateway、Tomcat开启JVM远程监控功能等





    网上的大多数文章都配置的是被动模式(即zabbix server 去想java进程去取数据),这样会造成zabbix server的压力过大,所以应该采用主动模式(写一个zabbix类,然后主动去上报数据)

    代码如下:

    zabbix.py

    cat zabbix.py
    #!/usr/bin/python
    import os
    import time
    import socket
    import struct
    import cPickle
    import logging
    try:
        from hashlib import sha1
    except ImportError:
        from sha import sha as sha1
    try:
        import json
    except ImportError:
        import simplejson as json
    DUMP = ‘dump‘
    if not os.path.isdir(DUMP):
        os.makedirs(DUMP, mode=0755)
    class Zabbix(object):
        logger = logging.getLogger(‘zabbix‘)
        def __init__(self, values=None):
            if values is not None:
                self.__dict__[‘values‘] = values
        def __getattr__(self, name):
            if name in (‘values‘):
                return self.__dict__[name]
            return None
        def __setattr__(self, name, value):
            if name == ‘values‘:
                self.__dict__[name] = value
        def gen_request(self, jsons):
            if isinstance(jsons, basestring):
                data = ‘%s\n‘ % jsons
            else:
                data = json.dumps(jsons)
            header = ‘ZBXD\x01‘
            datalen = struct.pack(‘Q‘, len(data))
            return header + datalen + data
        def dump(self, host, port, jsons):
            data = {‘host‘: host, ‘port‘: port, ‘jsons‘: jsons}
            hash = sha1(json.dumps(data)).hexdigest()
            path = ‘%s.%s.%d.%s.error‘ % (host, port, int(time.time()), hash)
            try:
                write = open(os.path.join(DUMP, path), ‘wb‘)
                cPickle.dump(data, write, -1)
                write.close()
            except:
                self.logger.exception(‘cannot dump to file %s‘, path)
        def get_zbx_result(self, host, port, jsons):
            retry = 3
            while retry:
                try:
                    data = self._get_zbx_result(host, port, jsons)
                    if data is None:
                        break
                    return data
                except socket.error:
                    self.logger.exception(‘cannot communit with zabbix‘)
                time.sleep(5)
                retry -= 1
            self.logger.error(‘cannot send data to zabbix server‘)
            self.dump(host, port, jsons)
        def _get_zbx_result(self, host, port, jsons):
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            print host,port,jsons
            sock.connect((host, port))
            sock.send(self.gen_request(jsons))
            print "send %s" % self.gen_request(jsons)
            self.logger.debug(‘sent %s‘, jsons)
            recv = sock.recv(5)
            if recv != ‘ZBXD\x01‘:
                self.logger.error(‘Invalid Response‘)
                self.dump(host, port, jsons)
                return None
            recv = sock.recv(8)
            (datalen,) = struct.unpack(‘Q‘, recv)
            data = sock.recv(datalen)
            sock.close()
            self.logger.debug(‘received %s‘, data)
            return data
        def getvalue(self):
            # shoulde be {host: {key: value}}
            return self.values
        def run(self):
            hostvalues = self.getvalue()
            if not isinstance(hostvalues, dict):
                self.logger.error(‘invalid hostvalues: %s‘, str(hostvalues))
                return False
            clock = int(time.time())
            jsons = {
                ‘request‘: ‘agent data‘,
                ‘data‘: [],
                ‘clock‘: clock,
            }
            data = jsons[‘data‘]
            for host, values in hostvalues.iteritems():
                for key, value in values.iteritems():
                    data.append({
                        ‘host‘: host,
                        ‘key‘: key,
                        ‘value‘: value,
                        ‘clock‘: clock,
                    })
            return self.get_zbx_result(ZBX_HOST, ZBX_PORT, jsons)
        def getjmx(self, host, port, keys):
            jsons = {
                ‘request‘: ‘java gateway jmx‘,
                ‘conn‘: host,
                ‘port‘: port,
                ‘keys‘: keys,
            }
            return self.get_zbx_result(JMX_HOST, JMX_PORT, jsons)
    ZBX_HOST = ‘zabbix.server.com‘
    ZBX_PORT = 10051
    JMX_HOST = ‘localhost‘
    JMX_PORT = 10052
    handler = logging.FileHandler(filename=‘/tmp/zabbix.%s.log‘ % time.strftime(‘%Y%m%d‘), mode=‘a‘)
    formatter = logging.Formatter(‘%(asctime)s %(name)s %(lineno)s %(levelname)s %(message)s‘)
    handler.setFormatter(formatter)
    logger = logging.getLogger()
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)
    if __name__ == ‘__main__‘:
        zbx = Zabbix()
        print zbx.getjmx(‘localhost‘, 8081, [‘jmx["Standalone:type=Manager,path=/,host=localhost",activeSessions]‘, ‘jmx["java.lang:type=Runtime",Uptime]‘, ‘jmx["Catalina:type=GlobalRequestProcessor,name=\\"http-bio-8080\\"",bytesSent]‘])
        pass



    cat zabbix_wiki_node1_java.py   

    #!/usr/bin/env python
    #fileencoding: utf-8
    ITEMS = [
    ‘jmx["java.lang:type=ClassLoading",LoadedClassCount]‘,
    ‘jmx["java.lang:type=ClassLoading",TotalLoadedClassCount]‘,
    ‘jmx["java.lang:type=ClassLoading",UnloadedClassCount]‘,
    ‘jmx["java.lang:type=Memory",HeapMemoryUsage.committed]‘,
    ‘jmx["java.lang:type=Memory",HeapMemoryUsage.max]‘,
    ‘jmx["java.lang:type=Memory",HeapMemoryUsage.used]‘,
    ‘jmx["java.lang:type=Memory",NonHeapMemoryUsage.committed]‘,
    ‘jmx["java.lang:type=Memory",NonHeapMemoryUsage.max]‘,
    ‘jmx["java.lang:type=Memory",NonHeapMemoryUsage.used]‘,
    ‘jmx["java.lang:type=MemoryPool,name=Code Cache",Usage.committed]‘,
    ‘jmx["java.lang:type=MemoryPool,name=Code Cache",Usage.max]‘,
    ‘jmx["java.lang:type=MemoryPool,name=Code Cache",Usage.used]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Eden Space",Usage.committed]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Eden Space",Usage.max]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Eden Space",Usage.used]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Old Gen",Usage.committed]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Old Gen",Usage.max]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Old Gen",Usage.used]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Perm Gen",Usage.committed]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Perm Gen",Usage.max]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Perm Gen",Usage.used]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Survivor Space",Usage.committed]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Survivor Space",Usage.max]‘,
    ‘jmx["java.lang:type=MemoryPool,name=PS Survivor Space",Usage.used]‘,
    ‘jmx["java.lang:type=OperatingSystem",MaxFileDescriptorCount]‘,
    ‘jmx["java.lang:type=OperatingSystem",OpenFileDescriptorCount]‘,
    ‘jmx["java.lang:type=Runtime",Uptime]‘,
    ‘jmx["java.lang:type=Threading",DaemonThreadCount]‘,
    ‘jmx["java.lang:type=Threading",PeakThreadCount]‘,
    ‘jmx["java.lang:type=Threading",ThreadCount]‘,
    ‘jmx["java.lang:type=Threading",TotalStartedThreadCount]‘,
    ‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",bytesReceived]‘,
    ‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",bytesSent]‘,
    ‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",errorCount]‘,
    ‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",processingTime]‘,
    ‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",requestCount]‘,
    ‘jmx["Standalone:type=Manager,path=/,host=localhost",activeSessions]‘,
    ‘jmx["Standalone:type=Manager,path=/,host=localhost",maxActiveSessions]‘,
    ‘jmx["Standalone:type=Manager,path=/,host=localhost",maxActive]‘,
    ‘jmx["Standalone:type=Manager,path=/,host=localhost",rejectedSessions]‘,
    ‘jmx["Standalone:type=Manager,path=/,host=localhost",sessionCounter]‘,
    ‘jmx["Standalone:type=ProtocolHandler,port=8090",compression]‘,
    ‘jmx["Standalone:type=ThreadPool,name=http-8090",currentThreadCount]‘,
    ‘jmx["Standalone:type=ThreadPool,name=http-8090",currentThreadsBusy]‘,
    ‘jmx["Standalone:type=ThreadPool,name=http-8090",maxThreads]‘,
    ]
    from zabbix import Zabbix
    from zabbix import json
    def getjmxkey(key):
        # key = key.replace(‘http-8080‘, ‘\\"http-bio-8080\\"‘)
        # key = key.replace(‘path=/‘, ‘context=/‘)
        return key
    def getjmxvalue(value):
        if isinstance(value, dict):
            return value.get(‘value‘, u‘‘).encode(‘utf8‘)
        return ‘‘
    if __name__ == ‘__main__‘:
        host = ‘it-tw01‘
        zbx = Zabbix()
        jmxkeys = [getjmxkey(x) for x in ITEMS]
        data = zbx.getjmx(‘it-tw01‘, ‘8410‘, jmxkeys)
        try:
            results = json.loads(data)
        except:
            results = {}
        if isinstance(results, dict) and results[‘response‘] == ‘success‘:
            jmxvalues = [getjmxvalue(x) for x in results.get(‘data‘, [])]
            hostvalues = {host: dict(zip(ITEMS, jmxvalues))}
            Zabbix(hostvalues).run()
    # vim: set sta sw=4 et:


    crontab

    * * * * * /home/sankuai/monitor/zabbix_wiki_node1_java.py


    zabbix

    /etc/zabbix# ls

    zabbix_agentd.conf  zabbix_agentd.confn-place  zabbix_agentd.d  zabbix_java_gateway.conf


    it-tw01需要关联的模板见附件




    特别注意:

    编译安装zabbix server需要加上--enable-java以支持jmx监控,如果之前的zabbix server没加,那么请重新编译安装,参考编译参数

    安装软件

    yum install -y java java-devel zabbix-java-gateway

    更多的请参考这个文章:http://www.iyunv.com/thread-269939-1-1.html


    zabbix使用zabbix_java_gateway 监控java应用进程

    标签:zabbix java jmx zabbix_java_gateway

    原文:http://tenderrain.blog.51cto.com/9202912/1878822

    展开全文
  • 为了实时了解到MySQL主从同步的状态,我们可以有多种方式,简单快捷的方式就是使用shell脚本,但是我们这里要说的是用zabbix来做监控,操作步骤如下。1、 添加一个免密用户,例如zabbix,用于执行查询slave状态用...
  • 二、需求说明:需使用Zabbix-server监控每个Agent上的jvm进程(监控项具体在模板中展示)三、准备环境:1.jvm.py脚本(非本人原创,从Github上直接copy的,此处附上Github地址,可直接去目标地址查看相关说明)2....
  • 用于zabbix监控脚本-批量获取docker容器名称及容器中的java进程ID,将结果格式化为json格式,直接返回给zabbix
  • 1.编辑自动发现脚本自动发现脚本只支持JSON格式#!/usr/bin/env python# -*- coding:utf-8 -*-import commandsimport psutilimport threadingimport json# 获取所有java进程的pidPids=commands.getoutput('pidof java...
  • java_pid=`netstat -lnpt |grep 'java'|awk '{print $NF'}|awk NR==1 |awk -F '/' '{print $1'}` # 截取$jstat命令的位置 jstat=/usr/local/jdk-1.8/bin/jstat #jstat_check=$(/usr/local...
  • 一:简介使用Python psutil模块,查找java模块,并获取启动命令,结合zabbix监控自动监控。点击下载二:操作发现脚本#!/usr/bin/env python# coding:utf-8import psutilimport reimport jsondef thread():try:data =...
  • 用于zabbix监控脚本-批量获取docker容器名称及容器中的java进程ID,将结果格式化为json格式,直接返回给zabbix
  • zabbix_get是zabbix获取监控项的可执行文件,通过指定监控的机器以及端口、监控key,可以获取相应的监控value。...我们可以通过java-proxy对java进行jmx监控,获取java-proxy的监控项比较特殊,所以需要具体的脚本
  • zabbix 监控tomcat zabbix需要增加zabbix-java-gateway服务 tomcat增加JMX模块的使用,会启动一个端口 JMX在Java编程语言中定义了应用程序以及网络管理和监控的体系结构、设计模式、应用程序接口以及服务。...
  • zabbix自动发现JAVA进程,并进行自动添加监控JAVA 进程的JVM数据,统计分析告警监控。 支持多种中间件,tomcat、weblogic、微服务方式部署JAVA应用监控。...自带发现脚本和监控脚本,以及zabbix导入模板。
  • 脚本1检测kafka消费组的消费者数量是否大于0 #!/bin/bash export JAVA_HOME=/opt/appl/tomcat/jdk value=`timeout 15 /opt/appl/kafka/kafka_2.11-2.1.1/bin/kafka-consumer-groups.sh --describe --bootstrap-...
  • Zabbix监控Linux

    2020-11-10 12:04:08
    Linux下Zabbix客户端编译安装 添加监控项目有多种方式 simple check,被监控的服务器无需安装客户端,如ping... External check,zabbix server上可编写监控脚本 Jmx agent,监控java进程 客户端监控、简单监控比
  • zabbix监控添加JMX实现对tomcat的监控1.1安装jdk和tomcat1.2编辑脚本文件1.3启动tomcat1.4安装zabbix-java-gateway软件1.5编辑zabbix_java_gateway.conf 文件1.6编辑zabbix-server.conf配置文件并重启zabbix-server...
  • Zabbix在线监控tomcat的线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。 ...
  • zabbix通过orabbix和自定义脚本监控oracle数据库 原文地址http://www.iyunv.com/thread-94249-1-1.html 由于公司要上oracle数据库,需要对这个东西惊醒监控,于是去网上淘资料,发现有一个套件orabbix监控oracle...
  • 一、介绍 添加监控项目有多种方式 simple check,被监控的服务器无需安装客户端,如...External check,zabbix server上可编写监控脚本 Jmx agent,监控java进程 环境 zabbix server: 10.0.0.104 被监控服务器: 10
  • 由于研究过php和java的微信告警发送,后来发现目前的微信告警需求相对不复杂,通过shell脚本可以满足目前的zabbix微信告警需求。本文讲解的是通过shell脚本进行zabbix告警通过微信发送。一、在zabbix的发送告警的的...
  • Zabbix监控JVM(微服务进程)1、ZabbixServer端配置Zabbix服务器需安装java,编译需添加启动参数--enable-java本次安装的编译参数为:./configure --prefix=/data/zabbix/ --enable-server --enable-agent --with-mysq...
  • 本文主要写了在Linux下如何用Shell脚本解析json数据,以便于在Zabbix中添加适合于业务应用的监控项。 为什么要使用json? json作为一种文本化的数据格式(文本化协议),符合UNIX编程的哲学,既符合透明性(透明性:...
  • zabbix监控oracle

    2019-05-21 13:49:56
    安装前的环境准备1. 确保JRE环境,使用java命令可以识别2. 修改zabbixserver和agent的host文件,但在Zabbix中添加... run.sh脚本java要替换为绝对路径,如果zabbix不是安装在/opt/zabbix下,启动脚本也要修改路径4...
  • 概述zabbix监控tomcat只有一个zabbix-java-gateway,可以部署在zabbix-sever端也可以部署在其他机器上,需要和zabbix-server网络可达。数了下目前生产的用不同的tomcat端口大概有30个,如果用一个tomcat端口对应一个...

空空如也

空空如也

1 2 3 4 5
收藏数 81
精华内容 32
关键字:

java监控脚本zabbix

java 订阅