设为首页 收藏本站
查看: 1328|回复: 0

[经验分享] Zabbix微信个人账号告警

[复制链接]

尚未签到

发表于 2019-1-17 14:03:28 | 显示全部楼层 |阅读模式
  前言:
  最近研究zabbix告警,网上看了帖子有各式各样姿势:电话语音告警,邮件告警,短信告警,微信公众号告警等等等..姿势五花八门,真是纠结。
  电话语音告警,短信告警首先pass 前者花钱,后者通过设置139邮箱,就可以实现伪短信告警效果。
  剩下邮件告警与微信公众号告警。邮件告警已经在部署的时候配置完毕,剩下这个微信公众号告警,查一下帖子,申请各种麻烦。那么有没有基于微信个人账号的告警呢?想到这个点,马上github一番。
  搜索到一些优秀的开源代码:https://github.com/0x5e/wechat-deleted-friends

  及封包:https://github.com/xiangzhai/qwx/blob/master/doc/protocol.md
  

  经过一番思考,大致思路如下:
  微信WEB保持活动状态,通过不断使用zabbix api抓取故障告警,入库后微信发送告警给相关人员。

  

  一 需求实现具体思路

  

  实现该需求是得有多个线程同时进行的

  •   微信心跳,微信WEB版保持活动状态。

  •   ZABBIX API ,不断请求zabbix告警,发现告警后,判断后入库。
  •   使用数据库不断查询告警,如果发现符合条件告警则发送告警给相关人员。
      

  

  二 部分代码及注释
  第一部分:wechat

# coding=utf-8
#伪装请求头
headers = {'User-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36'}
myRequests = requests.Session()
myRequests.headers.update(headers)
DEBUG = False
#微信类
class WeChat(object):
    def __init__(self):
        self.uuid = ''
        self.base_uri = ''
        self.push_uri = ''
        self.redirect_uri = ''
        self.BaseRequest = {}
        self.skey = ''
        self.wxuin = ''
        self.wxsid = ''
        self.skey = ''
        self.deviceId = 'e' + repr(random())[2:17]     #随机生成15位机器码
        self.pass_ticket = ''
        self.MemberList =[]
        self.ContactList = []
        self.AlarmFriends =[]
        self.Intervals = ''
        self.xintiao = ''
    #获取UUID
    def Get_UUID(self):
        url = 'https://login.weixin.qq.com/jslogin'
        params = {
            'appid': 'wx782c26e4c19acffb',
            'fun': 'new',
            'lang': 'zh_CN',
            '_': int(time.time()),
        }
        r = myRequests.get(url=url, params=params)
        r.encoding = 'utf-8'
        data = r.text
        #       data返回,code=200为状态.uuid="IZTW06WnSg=="为uuid
        #   window.QRLogin.code = 200; window.QRLogin.uuid = "IZtWO6WnSg==";
        # 正则匹配:匹配出状态码    以及UUID
        regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"'
        PM = re.search(regx, data)
        code = PM.group(1)
        if code == '200':
            self.uuid = PM.group(2)
            return True
        return False
    #   windows下直接打开二维码图
    def _openWinQRCodeImg(self):
        url = 'https://login.weixin.qq.com/qrcode/' + self.uuid
        params = {
            't': 'webwx',
            '_': int(time.time())
        }
        r = myRequests.get(url=url, params=params)
        f = open(QRImagePath, 'wb')
        f.write(r.content)
        f.close()
        time.sleep(1)
        os.startfile(QRImagePath)
    #   Linux下的二维码处理
    def _printQR(self, mat):
        for i in mat:
            BLACK = '\033[40m  \033[0m'
            WHITE = '\033[47m  \033[0m'
            print (''.join([BLACK if j else WHITE for j in i]))
    def _str2qr(self, str):
        qr = qrcode.QRCode()
        qr.border = 1
        qr.add_data(str)
        mat = qr.get_matrix()
        self._printQR(mat)  # qr.print_tty() or qr.print_ascii()
    #   判断操作系统,选择打开二维码扫描方式
    def genQRCode(self):
        if sys.platform.startswith('win'):
            self._openWinQRCodeImg()
        else:
            self._str2qr('https://login.weixin.qq.com/l/' + self.uuid)
    #等待登陆
    def WaitForLogin(self, tip=1):
        time.sleep(tip)
        url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (
            tip, self.uuid, int(time.time()))
        r = myRequests.get(url=url)
        r.encoding = 'utf-8'
        data = r.text
        #   data返回:
        #   window.code = 201;
        #判断返回码
        regx = r'window.code=(\d+);'
        pm = re.search(regx, data)
        code = pm.group(1)
        if code == '201':  # 已扫描
            print('
  • 成功扫描,请在手机上点击确认以登录')
            elif code == '200':  # 已登录
                print('[.]正在登录...')
                regx = r'window.redirect_uri="(\S+?)";'
                pm = re.search(regx, data)
                self.redirect_uri = pm.group(1) + '&fun=new'
                base_uri = self.redirect_uri[:self.redirect_uri.rfind('/')]
                # push_uri与base_uri对应关系(排名分先后)
                services = [
                    ('wx2.qq.com', 'webpush2.weixin.qq.com'),
                    ('qq.com', 'webpush.weixin.qq.com'),
                    ('web1.wechat.com', 'webpush1.wechat.com'),
                    ('web2.wechat.com', 'webpush2.wechat.com'),
                    ('wechat.com', 'webpush.wechat.com'),
                    ('web1.wechatapp.com', 'webpush1.wechatapp.com'),
                ]
              #  self.push_uri = self.base_uri
                self.push_uri = base_uri
                for (searchUrl, pushUrl) in services:
                    if base_uri.find(searchUrl) >= 0:
                        self.push_uri = 'https://%s/cgi-bin/mmwebwx-bin' % pushUrl
                        self.base_uri = 'https://%s/cgi-bin/mmwebwx-bin' % searchUrl
                        break
            elif code == '408':  # 超时
                pass
            # elif code == '400' or code == '500':
            return code
        #登陆
        def login(self):
            r = myRequests.get(url=self.redirect_uri)
            r.encoding = 'utf-8'
            data = r.text
        #    print (data)
            # data返回
            #   < ret > 0 < / ret > < message > OK < / message >
            #   < skey >XXXX < skey >
            #   < wxsid > XXXX < / wxsid >
            #   < wxuin > XXXX < / wxuin >
            #   < pass_ticket > XXXX < / pass_ticket >
            #   < isgrayscale > 1 < / isgrayscale >
            #解析XML文件
            doc = xml.dom.minidom.parseString(data)
            root = doc.documentElement
            for node in root.childNodes:
                if node.nodeName == 'skey':
                    self.skey = node.childNodes[0].data
                elif node.nodeName == 'wxsid':
                    self.wxsid = node.childNodes[0].data
                elif node.nodeName == 'wxuin':
                    self. wxuin = node.childNodes[0].data
                elif node.nodeName == 'pass_ticket':
                    self.pass_ticket = node.childNodes[0].data
        #    print('skey: %s, wxsid: %s, wxuin: %s, pass_ticket: %s' % (skey, wxsid,wxuin, pass_ticket))
            if not all((self.skey, self.wxsid, self.wxuin, self.pass_ticket)):
                return False
            self.BaseRequest = {
                'Uin': int(self.wxuin),
                'Sid': self.wxsid,
                'Skey': self.skey,
                'DeviceID': self.deviceId,
            }
         #   print (self.push_uri)
            return True
        def webwxinit(self):
            url = ( self.base_uri +'/webwxinit?pass_ticket=%s&skey=%s&r=%s' \
                    % (self.pass_ticket, self.skey, int(time.time())))
            params = {'BaseRequest': self.BaseRequest}
            headers = {'content-type': 'application/json; charset=UTF-8'}
            r = myRequests.post(url=url, data=json.dumps(params), headers=headers)
            r.encoding = 'utf-8'
            data = r.json()
            self.SyncKey = data['SyncKey']
            self.User = data['User']
            if False:
                f = open(os.path.join(os.getcwd(), 'webwxinit.json'), 'wb')
                f.write(r.content)
                f.close()
            self.synckey = '|'.join([str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List']])
            state = self.responseState('webwxinit', data['BaseResponse'])
            return state
        def webwxstatusnotify(self):
            url = self.base_uri + \
                '/webwxstatusnotify?lang=zh_CN&pass_ticket=%s' % (self.pass_ticket)
            params = {
                'BaseRequest': self.BaseRequest,
                "Code": 3,
                "FromUserName": self.User['UserName'],
                "ToUserName": self.User['UserName'],
                "ClientMsgId": int(time.time())
            }
            r = myRequests.post(url=url, params=json.dumps(params))
            data = r.json()
            state = self.responseState('WexinStatusNoTify',data['BaseResponse'])
            #return data['BaseResponse']['Ret'] == 0
            return state
        #获取好友列表
        def webwxgetcontact(self):
            url = (self.base_uri +'/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (\
                    self.pass_ticket, self.skey, int(time.time())))
            headers = {'content-type': 'application/json; charset=UTF-8'}
            r = myRequests.post(url=url, headers=headers)
            r.encoding = 'utf-8'
            data = r.json()
            if False:
                f = open(os.path.join(os.getcwd(), 'webwxgetcontact.json'), 'wb')
                f.write(r.content)
                f.close()
            self.MemberList = data['MemberList']
            SpecialUsers = ["newsapp", "fmessage", "filehelper", "weibo", "qqmail", "tmessage", "qmessage",\
                            "qqsync","floatbottle", "lbsapp", "shakeapp", "medianote", "qqfriend", "readerapp",\
                            "blogapp", "facebookapp", "masssendapp","meishiapp", "feedsapp", "voip",\
                            "blogappweixin", "weixin", "brandsessionholder", "weixinreminder",\
                            "wxid_novlwrv3lqwv11", "gh_22b87fa7cb3c", "officialaccounts",\
                            "notification_messages", "wxitil", "userexperience_alarm"]
            #将列表中特殊账号删除
            for i in range(len(self.MemberList) - 1, -1, -1):
                Member = self.MemberList
                if Member['VerifyFlag'] & 8 != 0:  # 公众号/服务号
                    self.MemberList.remove(Member)
                elif Member['UserName'] in SpecialUsers:  # 特殊账号
                    self.MemberList.remove(Member)
                elif Member['UserName'].find('@@') != -1:  # 群聊
                    self.MemberList.remove(Member)
                elif Member['UserName'] ==  self.User:  # 自己
                    self.MemberList.remove(Member)
            self.ContactList = self.MemberList
            return True
        #发送信息
        def webwxsendmsg(self, word, to='filehelper'):
            url = self.base_uri + \
                  '/webwxsendmsg?pass_ticket=%s' % (self.pass_ticket)
            clientMsgId = str(int(time.time() * 1000)) + \
                          str(random())[:5].replace('.', '')
            params = {
                'BaseRequest':{
                    "Uin": int(self.wxuin),
                    "Sid": self.wxsid,
                    "Skey":self.skey,
                    "DeviceID": self.deviceId,
                },
                'Scene': 0,
                'Msg':{
                    "Type": 1,
                    "Content": self._transcoding(word),
                    "FromUserName": self.User['UserName'],
                    "ToUserName": to,
                    "LocalID": clientMsgId,
                    "ClientMsgId": clientMsgId,
                }
            }
            headers = {'content-type': 'application/json; charset=UTF-8'}
            data = json.dumps(params, ensure_ascii=False).encode('utf8')
            r =myRequests.post(url,data=data,headers=headers)
            dic = r.json()
            state = self.responseState('SendMsg', dic['BaseResponse'])
            print (params)
            return state
          #  print (params)
        def Wx_Views(self):
            print ('[.]正在获取好友列表..')
            list = self.ContactList
            Alarmlist=[]
            # list = json.dump(List,ensure_ascii=False)
            for i in range(0,len(list)):
                if list:
                    list['id'] = i
                    Name = self._untostr(list['NickName'])
                    Rname = self._untostr(list['RemarkName'])
                    Id = i
                    #print (list)
                    print ('\t %d  \t姓名:%s \t 备注:%s' %(Id,Name,Rname))
                else:
                    print ('[!]获取失败!')
                    exit()
            while True:
                try:
                    iNput = raw_input("[.]请设置告警对象ID,使用空格隔开\n")
                    Alist = iNput.split(' ')
                except:
                    print ("[!]输入错误!")
                try:
                    for i in range(0,len(Alist)):
                        if Alist:
                            for j in range(0, len(list)):
                                if int(Alist) == list[j]['id']:
                                    print ('
  • 你设置的对象是:%s' % self._untostr(list[j]['NickName']))
                                    Alarmlist.append(list[j]['UserName'])
                                    self.AlarmFriends.append(list[j]['UserName'])
                                else:
                                    pass
                except:
                    continue
                if self.AlarmFriends:
                    Input = raw_input ("[!]确认设置(y/n)")
                    if Input == 'y':
                        self.AlarmFriends = Alarmlist
                        break
                    elif Input == 'n':
                        Alarmlist = []
                        self.AlarmFriends = []
                        pass
                    else:
                        Alarmlist = []
                        self.AlarmFriends = []
                        print ("[!]输入错误")
                else:
                    print ("[!]检测不到有效输入,请重试")
            print (self.AlarmFriends)
        def Wx_heartBeatLoop(self):
            while True:
                selector = self.syncCheck()
                if selector != '0':
                    self.webwxsync()
                time.sleep(int(self.xintiao))
                print ("
  • Wechat心跳正常..")
        def run(self):
            while True:
                time.sleep(5)
                SleepTime = int(self.Intervals)
                print("
  • 告警检测心跳..")
                Time = int(time.time())
                LastTime = Time - int(SleepTime)
                Select_sql = "SELECT * FROM wechat_sendmsg WHERE TIME BETWEEN %d and %d" % (LastTime,Time)
                data = db.select(Select_sql)
                # print (data)
                if data:
                    for i in data:
                        print (data )
                        triggerTime = self._untostr(i[0])
                        Hostname =  self._untostr(i[2])
                        HostIP = self._untostr(i[3])
                        Description = self._untostr(i[4])
                        level = self._untostr(i[5])
                        msg = """
    [!]发现告警
    告警服务器:%s
    告警时间:%s
    告警IP:%s
    告警项:%s
    告警级别:%s
    """ %(Hostname,triggerTime,HostIP,Description,level)
                        print (msg)
                        for j in range(0,len(self.AlarmFriends)):
                            self.webwxsendmsg(msg,self.AlarmFriends[j])
                            # print (j)
                            # print (self.AlarmFriends)
                else:
                    pass  第二部分:zabbix API
    from ZabbixTriggerDb import SQLiteDB
    myRequests = requests.Session()
    db = SQLiteDB
    class Zabbix(object):
        def __init__(self):
            self.Holist = []
            self.Zabbix_Address = ''
            self.Zabbix_Username=''
            self.Time = time.strftime('%Y-%m-%d %H:%M')
            self.Passwd = ''
            self.z_Intervals = ''
            self.w_Intervals = ''
            self.sleeptime = ''
            self.Trigger= []
            self.LastTrigger = []
            self.WxTriggerList = []
            #获取zabbix api token
        def get_auth(self):
            url = '%s/api_jsonrpc.php' % self.Zabbix_Address
            params = json.dumps({
                "jsonrpc": "2.0",
                "method": "user.login",
                "params": {
                    "user": self.Zabbix_Username,
                    "password": self.Passwd
                    },
                "id": 0
            })
            headers = {'content-type': 'application/json; charset=UTF-8'}
            r = myRequests.post(url=url, data=params, headers=headers)
            r.encoding = 'utf-8'
            data = r.json()
            return data['result']
            #获取zabbix监控主机列表
        def get_host(self):
            url = '%s/api_jsonrpc.php' % self.Zabbix_Address
            params = json.dumps({
                    "jsonrpc": "2.0",
                    "method": "host.get",
                    "params": {
                        "output":[
                            "hostid",
                            "name"
                        ],
                    "selectInterfaces":[
                        "interfaceid",
                        "ip",
                    ]
                    },
                    "id":2,
                    "auth":self.get_auth()
            })
            headers = {'content-type': 'application/json; charset=UTF-8'}
            r = myRequests.post(url=url, data=params, headers=headers)
            r.encoding = 'utf-8'
            data = r.json()
            self.Holist = data['result']
            return self.Holist
            
            #获取告警
        def get_trig(self,hostid):
            url = '%s/api_jsonrpc.php' % self.Zabbix_Address
            params = json.dumps({
                    "jsonrpc":"2.0",
                    "method":"trigger.get",
                    "params": {
                        "output": [
                                "triggerid",
                                "description",
                                "priority"
                                ],
                        "filter": {
                                "value": 1,
                                "hostid":hostid
                                },
                        "sortfield": "priority",
                        "sortorder": "DESC"
                             },
                    "auth": self.get_auth(),
                    "id":1
            })
            headers = {'content-type': 'application/json; charset=UTF-8'}
            r = myRequests.post(url=url, data=params, headers=headers)
            r.encoding = 'utf-8'
            data = r.json()
            if data['result']:
         #       text = json.dumps(data,ensure_ascii=False)
                return data['result']
            else:
                return None
    #告警信息入库
        def get_triggerlist(self):
            list = self.Holist
            if list:
                for i in range(0,len(list)):
                    # ip = self._untostr(list['interfaces']['ip'])
                    trigger = self.get_trig(list['hostid'])
                    Level = {'1':'DISASTER','2':'HIGH','3':'AVERAGE','4':'WARNING','5':'INFORMATION',\
                                '6':'NOT CLASSIFIED'}
                    if trigger != None:
                        Trigger = self._untostr(trigger[0]['description'])
                        level = self._untostr(trigger[0]['priority'])
                        name = self._untostr(list['name'])
                        ip = self._untostr(list['interfaces'][0]['ip'])
                        Datatime = time.strftime("%Y-%m-%d %H:%M", time.localtime())
                        Time = int(time.time())
                        z_LastTime = Time - int(self.z_Intervals)
                        w_LastTime = Time - int(self.w_Intervals)
                         #这个地方先查询在间隔时间段内有没有存在相同数据,如果没有就插入,有就跳过
                        zabbix_sql = "SELECT * FROM zabbix_trigger WHERE HOSTNAME='%s' and \
        DESCRIPTION='%s' and TIME BETWEEN %d and %d " % (name,Trigger,z_LastTime,Time)
                        z_data = db.select(zabbix_sql)
                        if z_data:
                            pass
                        else:
                            z_Inset_sql = "INSERT INTO zabbix_trigger(DATA,TIME,HOSTNAME,HOSTIP,DESCRIPTION,LEVEL)\
        VALUES('%s',%d,'%s','%s','%s','%s');" % (Datatime,Time,name,ip,Trigger,Level[level])
                            db.insert(z_Inset_sql)
                            #判断间隔时间内wechat_sendmsg表中是否存在相同输入,没有则插入
                        wechat_sql = "SELECT * FROM wechat_sendmsg WHERE HOSTNAME='%s' and \
        DESCRIPTION='%s' and TIME BETWEEN %d and %d limit 1" % (name, Trigger, w_LastTime, Time)
                        w_data = db.select(wechat_sql)
                        if w_data:
                            pass
                        else:
                            w_Inset_sql = "INSERT INTO wechat_sendmsg(DATA,TIME,HOSTNAME,HOSTIP,DESCRIPTION,LEVEL)\
        VALUES('%s',%d,'%s','%s','%s','%s');" % (Datatime, Time, name, ip, Trigger, Level[level])
                            db.insert(w_Inset_sql)
                      #这里思路是 设定时间内获取告警信息存入zabbix表,
                      #然后再另外设定一个时间写入weixin表 这样做是为了一个时间范围内不重复告警      
            else:
                print ("[!]获取主机列表失败,正在重新获取...")
                self.get_auth()
                self.get_host()
                self.get_triggerlist()
       #ZABBIX 心跳
        def run(self):
            while True:
                print ("
  • Zabbix心跳正常..")
                time.sleep(self.sleeptime)
                self.get_triggerlist()  第三部分:SQLite
    # coding=utf-8
    import sqlite3,os
    SQLiteDB = os.path.join(os.getcwd(), 'TriggerDB.db')
    DBCON = sqlite3.connect(SQLiteDB,check_same_thread=False) #多线程操作要开启这个选项
    DBCUR = DBCON.cursor()
    class SQLiteDB(object):
        @staticmethod
        def insert(sql):
            try:
                DBCUR.execute(sql)
            except sqlite3.Error as e:
                print ("[!]Insert Error! %s" % e.args[0])
            DBCON.commit()
        @staticmethod
        def select(sql):
            data = []
            try:
                DBCUR.execute(sql)
                data = DBCUR.fetchall()
            except sqlite3.Error as e:
                print ("[!]Slect Error!%s"% e.args[0])
            return data
            #初始化,新建两个表
        @staticmethod
        def CreatTable():
            zabbix_sql ="create table if not exists Zabbix_Trigger (DATA text,TIME integer,HOSTNAME text, \
                 HOSTIP text,DESCRIPTION text,LEVEL text);"
            weixin_sql = "create table if not exists Wechat_Sendmsg (DATA text,TIME integer,HOSTNAME text, \
                 HOSTIP text,DESCRIPTION text,LEVEL text);"
            try:
                DBCUR.execute(zabbix_sql)
                DBCUR.execute(weixin_sql)
            except sqlite3.Error as e:
                print ("[!]Creat Error! %s" % e.args[0])  第四部分:合体
    # coding=utf-8
    from Zabbix import Zabbix
    from ZabbixTriggerDb import SQLiteDB
    from WeChat import WeChat
    import os,sys,thread


    if __name__ == '__main__':
        db = SQLiteDB
        db.CreatTable()
        z = Zabbix()    #zabbix类
        w = WeChat()    #wechat类

        z.Zabbix_Address = 'http://Zabbix服务器地址'
        z.Zabbix_Username = 'zabbix用户'
        z.Passwd = 'zabbix密码'
        z.z_Intervals = 600     #zabbix告警入库间隔
        z.w_Intervals = 3600    #wechat告警入库间隔
        z.sleeptime = 10        #Zabbix心跳间隔
        w.Intervals = 3         #告警检测心跳间隔
        w.xintiao = 2           #微信心跳间隔
        z.get_auth()            #zabbix token
        z.get_host()            #zabbix hostlist
        z.get_triggerlist()     #zabbix triggerlist

        if not w.Get_UUID():
            print('[!]获取uuid失败,请重新运行!')
        print('
  • 正在获取二维码图片...')
        w.genQRCode()       #获取二维码
        while w.WaitForLogin() != '200':
            pass
        w.login()           #登陆
        w.webwxinit()       #初始化
        w.webwxgetcontact() #获取好友列表
        w.Wx_Views()        #设置告警好友

       #定义一个线程方法,加入zabbix运行线程与微信发送告警线程
        def RUN():
            thread.start_new(z.run, ())
            thread.start_new(w.run, ())
        RUN()
        #启动微信心跳(让微信保持在线状态)
        w.Wx_heartBeatLoop()  

      最终效果:





      





  • 运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-664484-1-1.html 上篇帖子: Zabbix4.0环境搭建 下篇帖子: Zabbix 4 安装初体验
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    扫码加入运维网微信交流群X

    扫码加入运维网微信交流群

    扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

    扫描微信二维码查看详情

    客服E-mail:kefu@iyunv.com 客服QQ:1061981298


    QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


    提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


    本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



    合作伙伴: 青云cloud

    快速回复 返回顶部 返回列表