Zabbix의Graphid를 통해 이미지 다운로드--제2판

24284 단어 vbszabbixwebapiNote
본 편을 읽기 전에 윗글을 읽어야 한다.https://blog.51cto.com/181647568/2480079
지난번 Powershell 버전의 그림에서 스크립트를 다운로드한 후에 피드백을 받았습니다.1. 이전 스크립트는 dll을 통해 데이터베이스에 접근하고 sql 문장을 통해graphid를 가져옵니다. 이것은 스크립트 이외에 dll가 있다는 것을 의미합니다.그리고 데이터베이스는 접근 권한을 개방해야 한다. 이것은 안전성이 떨어진다는 것을 의미한다.그리고 모든 생산 환경이 데이터에 들어가거나 데이터베이스를 수정할 수 있는 기회는 아니다.2.cookie는 브라우저에서 수동으로 패키지를 가져와야 합니다.이는 일부 IT에 어려움이 있습니다.3. itemkey는 죽은 것으로 작성되었습니다. itemkey의 그림을 많이 만들려면 여러 번 스크립트를 실행하거나 스크립트 코드를 수정해야 합니다.
내가 처음 본 블로그의 내용에 대한 깨우침을 얻어 개선을 하려고 한다.참조 문서:https://www.cnblogs.com/dreamer-fish/p/5485556.html생산 환경의 윈도우즈에python이 없기 때문에, 나는 아직 설치할 수 없다.그러나 리눅스에 있는python은 그 블로그의 코드를 사용할 수 없고 모듈이 부족합니다.그래서 이번에는 vbs로 코드를 실현하려고 합니다.파워셸의 쿠키,session 같은 대상은 너무 복잡합니다.
나는zabbix에서graph를 볼 때 http 캡처를 통해graphid가 발생하는 과정을 보지 못했다.나는zabbix에 독립된 웹api가 있는데 jsonrpc 형식의 데이터를 통해 통신을 하지만 웹 페이지가 정상적으로 방문할 때 이api를 사용하지 않는다는 것을 발견했다.공식 문서:https://www.zabbix.com/documentation/3.4/zh/manual/api
api의 검색 방법은 ql와 같습니다.zabbix를 통해agent_host는 hostid를 찾았고 hostid와 itemkey에 따라itemid를 찾았으며 Itemid를 통해graphid를 찾았습니다.그리고 사진을 다운로드하세요.이 jsonrpc의 과정은 쿠키를 사용할 필요가 없습니다.다음 그림의 과정은 쿠키가 필요합니다.유일한 차이점은 jsonrpc 웹api는 authcode를 가져오는 과정이 필요하고 사용자 이름과 비밀번호를 가져와야 하며 다음 과정은 이authcode를 사용해야 한다는 것이다.
쿠키를 얻기 위해서는 로그인하는 과정을 시뮬레이션해서 쿠키를 찾아야 할 수도 있습니다.로그인 인터페이스 index.php에서post 사용자 이름과 비밀번호를 통해 쿠키를 얻을 수 있습니다.이렇게 하면 코드에 쿠키가 아닌 사용자 이름과 비밀번호만 입력하면 더욱 친절해집니다.
다음은 코드입니다.
On Error Resume Next

Class VbsJson
    'Author: Demon
    'Date: 2012/5/3
    'Website: http://demon.tw
    Private Whitespace, NumberRegex, StringChunk
    Private b, f, r, n, t

    Private Sub Class_Initialize
        Whitespace = " " & vbTab & vbCr & vbLf
        b = ChrW(8)
        f = vbFormFeed
        r = vbCr
        n = vbLf
        t = vbTab

        Set NumberRegex = New RegExp
        NumberRegex.Pattern = "(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?"
        NumberRegex.Global = False
        NumberRegex.MultiLine = True
        NumberRegex.IgnoreCase = True

        Set StringChunk = New RegExp
        StringChunk.Pattern = "([\s\S]*?)([""\\\x00-\x1f])"
        StringChunk.Global = False
        StringChunk.MultiLine = True
        StringChunk.IgnoreCase = True
    End Sub

    'Return a JSON string representation of a VBScript data structure
    'Supports the following objects and types
    '+-------------------+---------------+
    '| VBScript          | JSON          |
    '+===================+===============+
    '| Dictionary        | object        |
    '+-------------------+---------------+
    '| Array             | array         |
    '+-------------------+---------------+
    '| String            | string        |
    '+-------------------+---------------+
    '| Number            | number        |
    '+-------------------+---------------+
    '| True              | true          |
    '+-------------------+---------------+
    '| False             | false         |
    '+-------------------+---------------+
    '| Null              | null          |
    '+-------------------+---------------+
    Public Function Encode(ByRef obj)
        Dim buf, i, c, g
        Set buf = CreateObject("Scripting.Dictionary")
        Select Case VarType(obj)
            Case vbNull
                buf.Add buf.Count, "null"
            Case vbBoolean
                If obj Then
                    buf.Add buf.Count, "true"
                Else
                    buf.Add buf.Count, "false"
                End If
            Case vbInteger, vbLong, vbSingle, vbDouble
                buf.Add buf.Count, obj
            Case vbString
                buf.Add buf.Count, """"
                For i = 1 To Len(obj)
                    c = Mid(obj, i, 1)
                    Select Case c
                        Case """" buf.Add buf.Count, "\"""
                        Case "\"  buf.Add buf.Count, "\\"
                        Case "/"  buf.Add buf.Count, "/"
                        Case b    buf.Add buf.Count, "\b"
                        Case f    buf.Add buf.Count, "\f"
                        Case r    buf.Add buf.Count, "\r"
                        Case n    buf.Add buf.Count, "
" Case t buf.Add buf.Count, "\t" Case Else If AscW(c) >= 0 And AscW(c) <= 31 Then c = Right("0" & Hex(AscW(c)), 2) buf.Add buf.Count, "\u00" & c Else buf.Add buf.Count, c End If End Select Next buf.Add buf.Count, """" Case vbArray + vbVariant g = True buf.Add buf.Count, "[" For Each i In obj If g Then g = False Else buf.Add buf.Count, "," buf.Add buf.Count, Encode(i) Next buf.Add buf.Count, "]" Case vbObject If TypeName(obj) = "Dictionary" Then g = True buf.Add buf.Count, "{" For Each i In obj If g Then g = False Else buf.Add buf.Count, "," buf.Add buf.Count, """" & i & """" & ":" & Encode(obj(i)) Next buf.Add buf.Count, "}" Else Err.Raise 8732,,"None dictionary object" End If Case Else buf.Add buf.Count, """" & CStr(obj) & """" End Select Encode = Join(buf.Items, "") End Function 'Return the VBScript representation of ``str(`` 'Performs the following translations in decoding '+---------------+-------------------+ '| JSON | VBScript | '+===============+===================+ '| object | Dictionary | '+---------------+-------------------+ '| array | Array | '+---------------+-------------------+ '| string | String | '+---------------+-------------------+ '| number | Double | '+---------------+-------------------+ '| true | True | '+---------------+-------------------+ '| false | False | '+---------------+-------------------+ '| null | Null | '+---------------+-------------------+ Public Function Decode(ByRef str) Dim idx idx = SkipWhitespace(str, 1) If Mid(str, idx, 1) = "{" Then Set Decode = ScanOnce(str, 1) Else Decode = ScanOnce(str, 1) End If End Function Private Function ScanOnce(ByRef str, ByRef idx) Dim c, ms idx = SkipWhitespace(str, idx) c = Mid(str, idx, 1) If c = "{" Then idx = idx + 1 Set ScanOnce = ParseObject(str, idx) Exit Function ElseIf c = "[" Then idx = idx + 1 ScanOnce = ParseArray(str, idx) Exit Function ElseIf c = """" Then idx = idx + 1 ScanOnce = ParseString(str, idx) Exit Function ElseIf c = "n" And StrComp("null", Mid(str, idx, 4)) = 0 Then idx = idx + 4 ScanOnce = Null Exit Function ElseIf c = "t" And StrComp("true", Mid(str, idx, 4)) = 0 Then idx = idx + 4 ScanOnce = True Exit Function ElseIf c = "f" And StrComp("false", Mid(str, idx, 5)) = 0 Then idx = idx + 5 ScanOnce = False Exit Function End If Set ms = NumberRegex.Execute(Mid(str, idx)) If ms.Count = 1 Then idx = idx + ms(0).Length ScanOnce = CDbl(ms(0)) Exit Function End If Err.Raise 8732,,"No JSON object could be ScanOnced" End Function Private Function ParseObject(ByRef str, ByRef idx) Dim c, key, value Set ParseObject = CreateObject("Scripting.Dictionary") idx = SkipWhitespace(str, idx) c = Mid(str, idx, 1) If c = "}" Then Exit Function ElseIf c <> """" Then Err.Raise 8732,,"Expecting property name" End If idx = idx + 1 Do key = ParseString(str, idx) idx = SkipWhitespace(str, idx) If Mid(str, idx, 1) <> ":" Then Err.Raise 8732,,"Expecting : delimiter" End If idx = SkipWhitespace(str, idx + 1) If Mid(str, idx, 1) = "{" Then Set value = ScanOnce(str, idx) Else value = ScanOnce(str, idx) End If ParseObject.Add key, value idx = SkipWhitespace(str, idx) c = Mid(str, idx, 1) If c = "}" Then Exit Do ElseIf c <> "," Then Err.Raise 8732,,"Expecting , delimiter" End If idx = SkipWhitespace(str, idx + 1) c = Mid(str, idx, 1) If c <> """" Then Err.Raise 8732,,"Expecting property name" End If idx = idx + 1 Loop idx = idx + 1 End Function Private Function ParseArray(ByRef str, ByRef idx) Dim c, values, value Set values = CreateObject("Scripting.Dictionary") idx = SkipWhitespace(str, idx) c = Mid(str, idx, 1) If c = "]" Then ParseArray = values.Items Exit Function End If Do idx = SkipWhitespace(str, idx) If Mid(str, idx, 1) = "{" Then Set value = ScanOnce(str, idx) Else value = ScanOnce(str, idx) End If values.Add values.Count, value idx = SkipWhitespace(str, idx) c = Mid(str, idx, 1) If c = "]" Then Exit Do ElseIf c <> "," Then Err.Raise 8732,,"Expecting , delimiter" End If idx = idx + 1 Loop idx = idx + 1 ParseArray = values.Items End Function Private Function ParseString(ByRef str, ByRef idx) Dim chunks, content, terminator, ms, esc, char Set chunks = CreateObject("Scripting.Dictionary") Do Set ms = StringChunk.Execute(Mid(str, idx)) If ms.Count = 0 Then Err.Raise 8732,,"Unterminated string starting" End If content = ms(0).Submatches(0) terminator = ms(0).Submatches(1) If Len(content) > 0 Then chunks.Add chunks.Count, content End If idx = idx + ms(0).Length If terminator = """" Then Exit Do ElseIf terminator <> "\" Then Err.Raise 8732,,"Invalid control character" End If esc = Mid(str, idx, 1) If esc <> "u" Then Select Case esc Case """" char = """" Case "\" char = "\" Case "/" char = "/" Case "b" char = b Case "f" char = f Case "n" char = n Case "r" char = r Case "t" char = t Case Else Err.Raise 8732,,"Invalid escape" End Select idx = idx + 1 Else char = ChrW("&H" & Mid(str, idx + 1, 4)) idx = idx + 5 End If chunks.Add chunks.Count, char Loop ParseString = Join(chunks.Items, "") End Function Private Function SkipWhitespace(ByRef str, ByVal idx) Do While idx <= Len(str) And _ InStr(Whitespace, Mid(str, idx, 1)) > 0 idx = idx + 1 Loop SkipWhitespace = idx End Function End Class Set wshnamed=wscript.arguments.named strGraphID = wshnamed.item("graphid") strPicSavePath = wshnamed.item("PicSavePath") strCookies = wshnamed.item("Cookies") Set fso = CreateObject("Scripting.FileSystemObject") zabbix_url = "192.1.31.66" zabbix_index = "http://" & zabbix_url & "/zabbix/index.php" zabbix_webapi= "http://" & zabbix_url & "/zabbix/api_jsonrpc.php" zabbix_username = "Admin" zabbix_password = "zabbix" Zabbix_cookie = GetZabbixCookie(zabbix_index,zabbix_username,zabbix_password) If(Zabbix_cookie = "")Then Wscript.Echo "Could not get Zabbix cookies, make sure your username and password is correct." End If Function GetAuthToken(url,username,password) Set Winhttp = CreateObject("WinHttp.WinHttpRequest.5.1") Winhttp.Open "POST", url Winhttp.SetRequestHeader "Content-Type", "application/json-rpc" If(cookie <> "")then Winhttp.SetRequestHeader "Cookie",cookie End If Winhttp.Send "{""jsonrpc"": ""2.0"", ""method"": ""user.login"", ""params"":{""user"": """&username&""",""password"": """&password&"""}, ""id"": 0}" Set json = New VbsJson GetAuthToken = json.Decode(Winhttp.ResponseText)("result") End Function Function GetDaySecond(Day) GetDaySecond = Day * 24 * 3600 End Function Function GetGraphid(url,AuthCode,itemid) Set Winhttp = CreateObject("WinHttp.WinHttpRequest.5.1") Winhttp.Open "POST", url Winhttp.SetRequestHeader "Content-Type", "application/json-rpc" Winhttp.Send "{""jsonrpc"": ""2.0"",""method"": ""graphitem.get"",""params"": {""output"": ""extend"",""expandData"": 1,""itemids"": """&itemid&"""},""auth"": """&AuthCode&""",""id"": 1}" Set json = New VbsJson GetGraphid = json.Decode(WinHttp.ResponseText)("result")(0)("graphid") End Function Function GetHostid(url,AuthCode,zabbix_agent_hostname) Set Winhttp = CreateObject("WinHttp.WinHttpRequest.5.1") Winhttp.Open "POST", url Winhttp.SetRequestHeader "Content-Type", "application/json-rpc" If(cookie <> "")then Winhttp.SetRequestHeader "Cookie",cookie End If Winhttp.Send "{""jsonrpc"": ""2.0"",""method"": ""host.get"",""params"": {""output"": ""extend"",""filter"": {""host"": """&zabbix_agent_hostname&"""}},""auth"": """&AuthCode&""",""id"": 1}" Set json = New VbsJson GetHostid = json.Decode(Winhttp.ResponseText)("result")(0)("hostid") End Function Function GetItemid(url,AuthCode,hostid,zabbix_item_key) Set Winhttp = CreateObject("WinHttp.WinHttpRequest.5.1") Winhttp.Open "POST", url Winhttp.SetRequestHeader "Content-Type", "application/json-rpc" If(cookie <> "")then Winhttp.SetRequestHeader "Cookie",cookie End If Winhttp.Send "{""jsonrpc"": ""2.0"",""method"": ""item.get"",""params"": {""output"": ""extend"",""hostids"": """ &hostid & """,""search"":{""key_"": """ & zabbix_item_key & """},""sortfield"": ""name""},""auth"": """&AuthCode&""",""id"": 1}" GetItemid = GetMid(Winhttp.ResponseText,"{""itemid"":""",""",""",1) End Function Function GetMid(strText, strFormer, strLater,intStartLocation) Dim FormerLocation Dim LaterLocation Dim PFormerLocation Dim PLaterLocation FormerLocation = InStr(intStartLocation, strText, strFormer) If (FormerLocation <> 0) Then FormerLocation = FormerLocation + Len(strFormer) LaterLocation = InStr(FormerLocation, strText, strLater) If (LaterLocation <> 0) Then GetMid = Mid(strText, FormerLocation, LaterLocation - FormerLocation) Exit Function End If End If GetMid = "" End Function Function GetZabbixCookie(zabbix_index,username,password) Set Winhttp = CreateObject("WinHttp.WinHttpRequest.5.1") Winhttp.Open "POST", zabbix_index Winhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" Winhttp.Send "name=" & username & "&password=" & password & "&autologin=1&enter=Sign+in" GetZabbixCookie = "zbx_sessionid=" & GetMid(winhttp.GetAllResponseHeaders,"zbx_sessionid=",";",1) & ";" End Function Sub DownloadZabbixPic(url,strPath,cookie) Set Winhttp = CreateObject("WinHttp.WinHttpRequest.5.1") Winhttp.Open "GET", url Winhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" If(cookie <> "")then Winhttp.SetRequestHeader "Cookie",cookie End If Winhttp.Send Set sGet = CreateObject("ADODB.Stream") sGet.Mode = 3 sGet.Type = 1 sGet.Open() sGet.Write(Winhttp.ResponseBody) sGet.SaveToFile strPath End Sub AuthCode = GetAuthToken(zabbix_webapi,zabbix_username,zabbix_password) If AuthCode = "" Then Wscript.Echo "Could not get AuthCode." Wscript.Quit End If CurrentFolder = fso.getfolder(".") CSV_Path = CurrentFolder&"\list.csv" If (fso.fileExists(CSV_Path)=0) Then Wscript.Echo "Could not find " & CSV_Path & "." Wscript.Quit End If set csv_file = fso.opentextfile(CSV_Path) csv_text = csv_file.readall csv_file.close PicSaveDir = CurrentFolder&"\"&replace(date(),"/","") If (fso.folderExists(PicSaveDir)=0) Then fso.createfolder(PicSaveDir) End If CSV_ReadLine = split(csv_text,vbCrlf) for i = 1 to ubound(CSV_ReadLine) step 1 CSV_ReadCol = split(CSV_ReadLine(i),"!") Zabbix_agent_host = CSV_ReadCol(0) ItemKey = CSV_ReadCol(1) PicSaveItemDir = PicSaveDir & "\" & Left(ItemKey,4) If (fso.folderExists(PicSaveItemDir)=0) Then fso.createfolder(PicSaveItemDir) End if PicSavePath = PicSaveItemDir & "\" & Zabbix_agent_host & ".png" Hostid = GetHostid(zabbix_webapi,AuthCode,Zabbix_agent_host) If (Hostid = "") Then Wscript.echo "Hostid is empty. Current host is: " & Zabbix_agent_host Else ItemID = GetItemid(zabbix_webapi,AuthCode,Hostid,ItemKey) If (Itemid = "") Then Wscript.echo "Itemid is empty. Current host is: " & Zabbix_agent_host & ". Current item is: "&ItemKey Else Graphid = GetGraphid(zabbix_webapi,AuthCode,itemid) If (graphid = "") Then Wscript.echo "Graphid is empty. Current host is: " & Zabbix_agent_host Else If (fso.fileExists(PicSavePath)) Then Wscript.echo "PNG alreadly exist. " & "Current host is: " & Zabbix_agent_host & ". Current item is: "&ItemKey Else DownloadZabbixPic "http://" & zabbix_url & "/zabbix/chart2.php?graphid=" & Graphid & "&period=" & GetDaySecond(30),PicSavePath,Zabbix_cookie Wscript.Echo Zabbix_agent_host & " " & ItemKey &" successfully save as " & PicSavePath End if End If End If End If Next

제가 이 스크립트의 사용 방법을 소개하겠습니다.첫 번째 단계에서 이 스크립트를 설정하면 오류가 발생할 때 프로그램을 종료하지 않고 계속 실행됩니다.그 다음은 json의 클래스로 vbs에서 json을 분석하는 데 사용되지만 이 json류는 약간의 문제가 있어서 json이 복잡하면 분석에 오류가 발생할 수 있습니다.그래서 만약 json이 길다면 나는 다른 명령을 사용하여 json의 값을 가져올 것이다.
이 스크립트가 정상적으로 실행되려면 검사할 호스트 이름을 수정하기 위해 csv 목록 파일이 필요합니다.그리고 이번에 나는 item 항목을 추가해서host의 어떤 item의 속표를 검사하기로 결정했다.이 중 csv의 기본 구분자는 ","이지만, "!"으로 바꿔야 합니다.Itemkey에 쉼표가 포함될 수 있기 때문에, 이 스크립트는 itemkey의 값을 잘못 분리할 수 있습니다.만약 같은 호스트가 두 가지 다른 item의 도표를 필요로 한다면, 두 줄을 써야 한다.첫 줄은 기본적으로 주석이기 때문에 무시한다.csv 파일은 excel에서 생성하고 수정할 수 있습니다.모든 텍스트 편집기에서 편집할 수도 있습니다.
이 csv는 다음과 같이 씁니다.
zabbixAgentHost!itemkey
Zabbix server!system.cpu.utils[,avg]
Zabbix server!vm.memory.useage

이 스크립트에서 변경되는 부분은 zabbix의 IP 주소(대응 변수: zabbix url), 사용자 이름(zabbix username), 암호(zabbix password)입니다.그리고 도표가 php를 생성하는 매개 변수도 있다.그림은 기본적으로 vbs가 있는 경로에 생성됩니다. 오늘 날짜에 생성된 폴더로 만들고 item 이름의 네 번째 폴더로 하위 폴더를 만들고, 그림은 대응하는 폴더에 저장됩니다.그림의 규칙은zabbixagent_hostname의 값이 추가되었습니다.png 접미사 이름입니다.그림이 이미 존재하면, 실행할 때 파일이 존재하지만, 존재하는 그림을 덮어쓰지 않습니다.
다음은 스크립트의function에 대한 설명입니다. GetAuthToken(url,username,password)은 사용자 이름 비밀번호를 통해 웹api authtoken을 가져옵니다.
GetGraphid(url,AuthCode,itemid)itemid를 통해graphid 가져오기
GetHostid(url, AuthCode, zabbix agent hostname)는 authcode 및 zabbix 를 통해agent_hostname 가져오기hostid
GetItemid(url, AuthCode,hostid,zabbix item key)hostid 및 itemkey를 통해itemid 가져오기
GetMid(strText,strFormer,strLater,intStartLocation)는 컴파일된 '텍스트 중간 텍스트 가져오기' 는 주로 두 문자열의 중간 결과를 추출하여 json이 정상적으로 해석되지 않을 때 텍스트 형식으로 json의 값을 가져오는 데 사용됩니다.
GetDay Second (Day) 는 N일의 초수를 계산하는데, 이 값은 후기에 chart2.php에서 표를 생성할 때 매개 변수의 값을 제공합니다.
GetZabbix Cookie(zabbix index, username, password)는 zabbix의 사용자 이름과 비밀번호를 사용하여 쿠키를 가져옵니다.쿠키는 정확한 이미지를 다운로드하는 데 성공하는 필수 조건입니다!
DownloadZabbixPic(url,strPath,cookie) 사실상 이 함수는 그림을 가져올 수 있는 것이 아니라 웹 페이지가 되돌아오는 내용을 이진 형식으로 파일로 저장합니다.쿠키도 사용할 수 있습니다.
스크립트가 list를 읽습니다.csv 파일의 정보 (디렉터리에 list. csv 파일이 있어야 함) 를 그림으로 변환합니다.그림이 생성된 파라미터를 주의하십시오. 스크립트의 DownloadZabbixPic를 검색해서zabbix가 생성한 도표의 파라미터를 볼 수 있습니다.주로 네 가지 파라미터가 비교적 중요한데 stime는 시작 시간을 나타내는 용법(yyyyMDDhhhmmss)은 과거에 대응했던 시간에서 현재까지의 데이터로 기본값을 채우지 않는다.period는 시간 단위를 초로 하고 getdaysecond로 초수를 계산할 수 있다. 기본값은 30일의 데이터이다. 바꾸려면 스스로 수정할 수 있고 이 데이터를 채우지 않는 것도 기본 30일 데이터이다.그리고 두 개의 값은 weight와 height인데, 이 두 개의 값은 그림의 길이와 넓이를 각각 제어한다.안 채워도 돼요.
cmd에서 cscript를 사용하여 이 vbs를 실행하십시오. 그렇지 않으면 오류 보고와 알림 정보가 정보 상자 형식으로 나타납니다.너는 끊임없이 탄창에 시달려 죽을 것이다.이 스크립트의 로그 파일로 cscript 명령을 로그로 바꿀 수 있습니다.

좋은 웹페이지 즐겨찾기