使用lld自动发现监控多实例redis
zabbix 可以通过常见的手段监控到各种服务,通过编写脚本来获取返回值并将获取到的值通过图形来展现出来,包括(系统、服务、业务)层面。可是有些时候在一些不固定的场合监控一些不固定的服务就比较麻烦。例如,服务器运行四台 redis,端口分别是 ,那么这时候如果需要监控则需要建立三个模板,分别对应不同的模板又要设置不同的 Shell Script 及 UserParameter 来监控不同端口的服务。 zabbix 有 LLD 特性(low level discovery),属于自动发现的范畴(该自动发现属于多服务的监控,是系统层面的),你会发现有很多要监控的对象大部分都是不固定的,到处都是LLD。换句话说,我们要监控的对象如果是固定的,那直接添加一个item就可以了,但是如果不是固定的,那就需要用LLD。 使用方法:
)使用netstat来捕获redis-server启用的端口,但zabbix-agent运行在zabbix账号下,故须给zabbix账号授权运行netstat -nltp的权限,在root用户下执行如下命令:
echo "zabbix ALL=(root) NOPASSWD:/bin/netstat" > /etc/sudoers.d/zabbix
echo 'Defaults:zabbix !requiretty' >> /etc/sudoers.d/zabbix )将qiueer目录、redis.py复制到 /usr/local/zabbix-agent/scripts 目录,供参考:
mkdir -p /usr/local/zabbix-agent/scripts
将 https://github.com/qiueer/zabbix/tree/master/Redis/qiueer 目录下的所有文件拷贝到/usr/local/zabbix-agent/scripts目录中 添加redis.py这个自动发现的脚本
# vim /usr/local/zabbix-agent/scripts/redis.py #!/usr/bin/env python
#encoding=utf-
import sys
import os
from optparse import OptionParser
import re from qiueer.python.slog import slog
from qiueer.python.cmds import cmds
from qiueer.python.filecache import filecache
from qiueer.python.utils import which class Redis(object):
def __init__(self, logpath, password=None, port=, debug=False):
self._logpath = logpath
self._password = password
self._port = port if port else
self._debug = debug
self._file_cache_path = "/tmp/.zabbix_memcache_%s.log" % (port)
self._file_cache = filecache(self._file_cache_path)
self._logger = slog(self._logpath, debug=debug, size=, count=) def get_redis_port_list(self):
# sudo权限,必须授予,在root用户下执行如下命令
"""
echo "zabbix ALL=(root) NOPASSWD:/bin/netstat" > /etc/sudoers.d/zabbix
echo 'Defaults:zabbix !requiretty' >> /etc/sudoers.d/zabbix
chmod /etc/sudoers.d/zabbix
""" cmdstr = "sudo netstat -nlpt | grep 'redis' | awk '{print $4}'|awk -F: '{print $2}'"
c2 = cmds(cmdstr, timeout=)
stdo = c2.stdo()
stde = c2.stde()
retcode = c2.code() (stdo_list, stde_list) = (re.split("\n", stdo), re.split("\n", stde))
logdict = {
"cmdstr": cmdstr,
"stdo": stdo,
"stde": stde,
"retcode": retcode,
"orders": ["cmdstr", "stdo", "stde", "retcode"],
} if retcode !=:
self._logger.dictlog(width=, level="error", **logdict)
return
else:
self._logger.dictlog(width=, level="info", **logdict) data = list()
for port in stdo_list:
if not port:continue
port = int(str(port).strip())
data.append({"{#REDIS_PORT}": port})
import json
return json.dumps({'data': data}, sort_keys=True, indent=, separators=(",",":")) def get_item(self, key, port=None, password=None, force=False):
"""
参数:
"""
# cmdstr = "redis-cli -h 172.16.155.21 -p 6379 info | grep 'used_cpu_sys' "
port = port if port else self._port
password = password if password else self._password if force == False:
value = self._file_cache.get_val_from_json(key)
logdict = {
"msg": "Try To Get From Cache File: %s" % self._file_cache_path,
"key": key,
"value": value,
"orders": ["msg", "key", "value"],
}
self._logger.dictlog(width=, level="info", **logdict)
if value: return value rds_cli_path = which("redis-cli")
## 适配编译安装,这里设置常用的路径
rds_paths_def = ["/usr/local/bin/redis-cli", "/bin/redis-cli", "/usr/local/redis-server/bin/redis-cli"] cmdstr = None
if rds_cli_path:
cmdstr = "%s -h 172.16.155.21 -p %s info" % (rds_cli_path, port)
if password:
cmdstr = "%s -h 172.16.155.21 -a %s -p %s info" % (rds_cli_path, password, port)
else:
for p in rds_paths_def:
if os.path.exists(p) == False: continue
cmdstr = "%s -h 172.16.155.21 -p %s info" % (p, port)
if password: cmdstr = "%s -h 172.16.155.21 -a %s -p %s info" % (p, password, port)
break c2 = cmds(cmdstr, timeout=)
stdo = c2.stdo()
stde = c2.stde()
retcode = c2.code() (stdo_list, stde_list) = (re.split("\n", stdo), re.split("\n", stde))
logdict = {
"cmdstr": cmdstr,
"stdo": stdo,
"stde": stde,
"retcode": retcode,
"orders": ["cmdstr", "stdo", "stde", "retcode"],
} if retcode !=:
self._logger.dictlog(width=, level="error", **logdict)
return
else:
self._logger.dictlog(width=, level="info", **logdict) resobj = {}
for line in stdo_list:
line = str(line).strip()
ln_ary = re.split(":", line)
if ln_ary and len(ln_ary) != :continue
dst_key = str(ln_ary[]).strip()
dst_val = str(ln_ary[]).strip()
resobj[dst_key] = dst_val
self._file_cache.save_to_cache_file(resobj)
return resobj.get(key, "") def main(passwd_file):
try:
usage = "usage: %prog [options]\ngGet Redis Stat"
parser = OptionParser(usage) parser.add_option("-l", "--list",
action="store_true", dest="is_list", default=False, help="if list all redis port") parser.add_option("-k", "--key",
action="store", dest="key", type="string",
default='blocked_clients', help="execute 'redis-cli info' to see more infomation") parser.add_option("-a", "--password",
action="store", dest="password", type="string",
default=None, help="the password for redis-server") parser.add_option("-p", "--port",
action="store", dest="port", type="int",
default=, help="the port for redis-server, for example: 6379") parser.add_option("-d", "--debug",
action="store_true", dest="debug", default=False,
help="if output all") parser.add_option("-f", "--force",
action="store_true", dest="force", default=False,
help="if force to parse command oupout") (options, args) = parser.parse_args()
if >= len(sys.argv):
parser.print_help()
return password = options.password
if not password and os.path.exists(passwd_file):
fd = open(passwd_file, 'r')
lines = fd.readlines()
fd.close()
for line in lines:
line = str(line).strip()
if line == "" or line.startswith("#"):continue
ln_ary = re.split(r"[|;|,|\s]+", line)
fport = int(ln_ary[])
if fport == int(options.port):
password = ln_ary[]
break logpath = "/tmp/zabbix_redis_info.log"
redis_ins = Redis(logpath, password=password, port=options.port, debug=options.debug)
if options.is_list == True:
print redis_ins.get_redis_port_list()
return print redis_ins.get_item(options.key, port=options.port, force=options.force) except Exception as expt:
import traceback
tb = traceback.format_exc()
print tb if __name__ == '__main__':
# redis密码存放的文件
redis_passwd_file = "/usr/local/zabbix-agent/scripts/.redis.passwd"
main(redis_passwd_file) )zabbix_agent.conf配置文件中需包含如下配置,注意脚本的位置:
## qiueer redis-stat for discovery
UserParameter=custom.redis.discovery, python /usr/local/zabbix-agent/scripts/redis.py --list
UserParameter=custom.redis.item[*],python /usr/local/zabbix-agent/scripts/redis.py -p $ -k $ )配置完成后,重启zabbix agent,例如:
service zabbix-agent restart )在zabbix前端导入模板:
Qiueer-Template:
Business-Redis-Discovery.xml )如果连接Redis需要账号密码,则需要配置端口、密码的对应关系,配置文件路径如下:
/usr/local/zabbix-agent/scripts/.redis.passwd(注意需给zabbix用户赋予只读权限)
内容类似如下,格式是: 端口 密码
42s#qdd [root@sdtw02 scripts]# cat .redis.passwd
cX8RvegIER0S
YwvmTGqD5YpP
8RJ4QYXen9Q
If4krh6x7cj2 PS:
)、)步骤中的路径/usr/local/zabbix-agent/scripts/根据实际情况修改 使用示例:
)获取redis端口列表:
[root@sdtw02 scripts]# python redis.py -l
/usr/local/zabbix-agent/scripts/qiueer/python/slog.py:: DeprecationWarning: object.__new__() takes no parameters
slog.__logger = object.__new__(cls, *args, **kwd)
{
"data":[
{
"{#REDIS_PORT}":
},
{
"{#REDIS_PORT}":
},
{
"{#REDIS_PORT}":
},
{
"{#REDIS_PORT}":
}
]
} )采集数据
[root@sdtw02 scripts]# python redis.py -p -k used_memory_rss 其他:
## 使用如下命令解析其输出来获取redis的端口
sudo netstat -nlpt | grep 'redis' | awk '{print $4}'|awk -F: '{print $2}' 几个坑: ①如果不能正常获取采集的数据,可以检查日志:
/tmp/zabbix_redis_info.log [-- ::] ERROR
cmdstr: /usr/local/bin/redis-cli -h 127.0.0.1 -a 3i0uULCGcX8RvegIER0S -p info
stdo:
stde: Could not connect to Redis at 127.0.0.1:: Connection refused
retcode: 从上面的日志可以看到连接被拒绝,我们自己手动连接也是一样,是因为redis的监听绑定在了内网ip上面,而不是绑定在了127.0.0.1上,修改即可
# sed -i 's#127.0.0.1#172.16.155.21#g' redis.py ②我们使用的是默认的python2..6可能执行redis.py时或出现一些警告信息,如下,这样无法正常获取数据
[root@sdtw02 scripts]# python redis.py -p -k used_memory_rss
/usr/local/zabbix-agent/scripts/qiueer/python/slog.py:: DeprecationWarning: object.__new__() takes no parameters
slog.__logger = object.__new__(cls, *args, **kwd) 修改 /usr/local/zabbix-agent/scripts/qiueer/python/slog.py 53行为如下即可:
slog.__logger = object.__new__(cls) ③获取不到数据
在zabbix服务端调试: [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k "custom.redis.discovery"
Traceback (most recent call last):
File "/usr/local/zabbix-agent/scripts/qiueer/python/slog.py", line , in __init__
file_handler = RotatingFileHandler(self._filename, mode='a',maxBytes=self._size**,backupCount=self._count)
File "/usr/lib64/python2.6/logging/handlers.py", line , in __init__
BaseRotatingHandler.__init__(self, filename, mode, encoding, delay)
File "/usr/lib64/python2.6/logging/handlers.py", line , in __init__
logging.FileHandler.__init__(self, filename, mode, encoding, delay)
File "/usr/lib64/python2.6/logging/__init__.py", line , in __init__
StreamHandler.__init__(self, self._open())
File "/usr/lib64/python2.6/logging/__init__.py", line , in _open
stream = open(self.baseFilename, self.mode)
IOError: [Errno ] Permission denied: '/tmp/zabbix_redis_info.log' {
"data":[
{
"{#REDIS_PORT}":
},
{
"{#REDIS_PORT}":
},
{
"{#REDIS_PORT}":
},
{
"{#REDIS_PORT}":
}
]
} 是因为zabbix用户没有log日志的权限,解决:
chown -R zabbix.zabbix /tmp/zabbix_redis_info.log 继续调试: [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,total_commands_processed] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,total_commands_processed] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,total_commands_processed] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,used_memory_peak] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,used_memory_peak] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,used_memory_peak] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,used_memory_peak] [root@u04zbx01 ~]# zabbix_get -s 1.1.1.1 -p -k custom.redis.item[,used_memory_peak]
使用lld自动发现监控多实例redis的更多相关文章
- zabbix使用自动发现监控esxi的磁盘存储storage
zabbix使用自动发现监控esxi的磁盘存储storage 在任意一台可以访问vcenter的zabbix-agent服务器上添加exsi的磁盘监控模板即可 创建模板过程: custom.esxi. ...
- 01 - zabbix | LLD自动发现
01 - zabbix | LLD自动发现 1. 原理 zabbix支持设置变量,用{#VAR_NAME}来表示.然后有一些系统保留的变量 2. 设置 2.1 交换机电源自动发现 名字写好后进进入 ...
- Prometheus基于consul自动发现监控对象 https://www.iloxp.com/archive/11/
Prometheus 监控目标为什么要自动发现 频繁对Prometheus配置文件进行修改,无疑给运维人员带来很大的负担,还有可能直接变成一个“配置小王子”,即使是配置小王子也会存在人为失误的情况 ...
- zabbix自动发现监控url
1.在监控客户机上 web_site_code_status.sh: #!/bin/bash UrlFile="/opt/scripts/WEB.txt" IFS=$'\n' we ...
- zabbix自动发现监控mysql
一. 数据库给只读权限 1.1 grant usage on *.* to 'zabbix'@'127.0.0.1' identified by 'zabbix'; flush privileges; ...
- 使用 zabbix 自动发现监控 MySQL
介绍 使用 zabbix 的 low-level 自动发现功能完成单主机多端口的监控, 详见low_level_discovery, 整体上监控类似 percona 的 zabbix 监控插件, 不过 ...
- Zabbix自动发现监控Tomcat进程
1.编辑自动发现脚本 自动发现脚本只支持JSON格式 #!/usr/bin/env python # -*- coding:utf-8 -*- import commands import psuti ...
- zabbix监控自动发现监控tomcat(V1)
背景说明: 由于zabbix监控使用自带的模版,只能监控主机上只有1个tomcat的场景适合,虽然网上很多朋友都是在每个监控项上面添加一个空格来解决问题.但是个人感觉这种方法还是蛮麻烦的,所以写一篇使 ...
- Sping Cloud hystrix.stream 自动发现-监控
相关组件安装脚本 [root@java_gateway4 java_tps]# cat cront_install.sh #!/bin/bashyum install jq -ymkdir /home ...
随机推荐
- 【leetcode-102,107,103】 二叉树的层次遍历
102. 二叉树的层次遍历 (1过,隐蔽错误花时间很多,简单题目本应很快,下次注意红色错误的地方) 给定一个二叉树,返回其按层次遍历的节点值. (即逐层地,从左到右访问所有节点). 例如:给定二叉树: ...
- UVA - 1401 | LA 3942 - Remember the Word(dp+trie)
https://vjudge.net/problem/UVA-1401 题意 给出S个不同的单词作为字典,还有一个长度最长为3e5的字符串.求有多少种方案可以把这个字符串分解为字典中的单词. 分析 首 ...
- Structured Streaming + Kafka Integration Guide 结构化流+Kafka集成指南 (Kafka broker version 0.10.0 or higher)
用于Kafka 0.10的结构化流集成从Kafka读取数据并将数据写入到Kafka. 1. Linking 对于使用SBT/Maven项目定义的Scala/Java应用程序,用以下工件artifact ...
- vue-router 编程式路由
$route -> 使用它的属性 $router-> 使用它的方法 编程式的导航,即js控制跳转 //声明式:<router-link :to="..."> ...
- Information Retrieval 倒排索引 学习笔记
一,问题描述 在Shakespeare文集(有很多文档Document)中,寻找哪个文档包含了单词“Brutus”和"Caesar",且不包含"Calpurnia&quo ...
- 实惠VPS推荐
1. Topmain 2. Virmach 3. BanwagonHost [备用地址1] [备用地址2] 4. HiFormance (跑路) 5. my.hosteons.com 6. . 以 ...
- IScroll5要防止重复加载
增加一个判断条件,ajax未返回前,设置为true,返回前设置为false,只有为false下才能够出发加载数据事件效果好很多.
- Coursera, Deep Learning 4, Convolutional Neural Networks - week2
Case Study (Note: 红色表示不重要) LeNet-5 起初用来识别手写数字灰度图片 AlexNet 输入的是227x227x3 的图片,输出1000 种类的结果 VGG VGG比Ale ...
- Spark On Yarn报警告信息 WARN yarn.Client: Neither spark.yarn.jars nor spark.yarn.archive is set, falling back to uploading libraries under SPARK_HOME.
1 贴出完整日志信息 // :: INFO client.RMProxy: Connecting to ResourceManager at hdp1/ // :: INFO yarn.Client: ...
- 推荐使用string
C-string(char* const char*) basic_string<>特化版本:string charwstring wchar_tu16string char16_tu32 ...