Read the above before reading this article: https://blog.51cto.com/181647568/2480079
After downloading the script from the last Powershell version of the picture, I received some feedback.
1. The last script accesses the database through dll and gets graphid through sql statement, which means there is a dll in addition to the script.And the database must have open access, which means less security.And not all production environments have the opportunity to enter data or modify databases.
2.Cookies need to be captured manually in the browser.This is difficult for some IT.
3. The itemkey is written to death. If you want to have more images of the itemkey, you need to run the script several times or modify the script code.
I'm going to make some improvements based on what I saw in the blog I started with.
Reference documents: https://www.cnblogs.com/dreamer-fish/p/5485556.html
Since python is not available on windows in the production environment, I cannot install it yet.But python on Linux has code that can't be used in that blog post, missing some modules.So this time I'm going to use vbs to implement the code.Objects such as powershell cookies, sessions are too complex.
I didn't see the process of graphid generation through http grabbing when zabbix was viewing the graph.I found that zabbix has a separate web api for communicating with data in jsonrpc format, but this api is not used when web pages are normally accessed.
Official documents: https://www.zabbix.com/documentation/3.4/zh/manual/api
The query method of the api is the same as that of sql.The hostid is found by zabbix_agent_host, the itemid by hostid and itemkey, and the graphid by Itemid.Then download the picture.This jsonrpc process does not require cookies.The process for the next image requires a cookie.
The only difference is that the jsonrpc webapi needs to fetch an authcode, which is obtained by using a username and password, which is needed in the next process.
In order to obtain a cookie, you may need to simulate a login process to retrieve the cookie.Cookies are available through the post username and password in the login interface index.php.This makes it more friendly for us to just fill in the code with a user name and password, not a cookie.
Here is the code:
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, "\n" 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
Let me show you how to use this script.The first section at the beginning sets up that the script will continue running without exiting the program if something goes wrong.
Then there is a JSON class, which is used to analyze JSON in vbs, but this JSON class is a bit problematic, as long as the JSON is complex, the analysis will be wrong.So if JSON is very long, I'll use another command to get the value of json.
The normal operation of this script also requires a list file of CSVS to modify the name of the hosts we need to check.And this time I added an item for the item to determine what item to check for the continuation table of the host.The default separator for csv is',', but we'll change it to'!'.Because Itemkey may contain commas, the subscript will mistakenly split the value of itemkey.If you need charts for two different items for the same host, you need to write two lines.The first line is a comment by default, so it's ignored.csv files can be generated and modified in excel.It can also be edited in any text editor.
This csv is written as follows:
zabbixAgentHost!itemkey Zabbix server!system.cpu.utils[,avg] Zabbix server!vm.memory.useage
The changes in this script include the IP address (corresponding variable: zabbix_url), user name (zabbix_username), and password (zabbix_password).There are also parameters for graph generation php.
Pictures will be generated by default at the path where vbs is located. Mr. will create a folder generated by today's date. Subfolders will be created in the first four bits of the item name, and the pictures will be placed in the corresponding folder.The clear rule for pictures is the value of zabbix_agent_hostname plus the.png suffix name.If the picture already exists, the file will be prompted to exist when running, but the existing picture will not be overwritten.
The following is an explanation of the function in the script:
GetAuthToken(url,username,password)
Obtain webapi authtoken with username password
GetGraphid(url,AuthCode,itemid)
Getting graphid from itemid
GetHostid(url,AuthCode,zabbix_agent_hostname)
Get hostid from authcode and zabbix_agent_hostname
GetItemid(url,AuthCode,hostid,zabbix_item_key)
Get itemid from hostid and itemkey
GetMid(strText, strFormer, strLater,intStartLocation)
Text_Retrieve Intermediate Text adapted from the refined module is mainly the result of taking out the middle of two strings to get the value of json in the form of text when json cannot be parsed properly.
GetDaySecond(Day)
Calculates the number of seconds in N days, which is used to provide a parameter value later in the table generation for chart2.php.
GetZabbixCookie(zabbix_index,username,password)
Get the cookie by zabbix's username and password.Cookies are essential for successful download to the correct picture!
DownloadZabbixPic(url,strPath,cookie)
In fact, this function does not just take pictures, it saves the content returned from a web page as a binary file.Cookies can also be used.
The script reads the information in the list.csv file (be sure to have a list.csv file in the same directory) and converts it to a picture.
Notice the parameters for the graph generation, and you can search Download ZabbixPic in the script to see the parameters for the graph generated by zabbix.There are four main parameters which are more important. The stime represents the start time usage (yyyyMMDDhhmmss) does not fill in the data which will default to the corresponding time in the past and now. The period represents the time unit which can be used to calculate seconds with getdaysecond s. The default is 30-day data. If you want to modify it yourself, it is also the default 30-day data.The other two values are weight and height, which control the length and width of the picture, respectively.Not filling in is also possible.
Please use cscript in cmd to run this vbs, otherwise the error and prompt information will appear as information box.You'll get bored with the endless bouncing boxes.You can redirect cscript commands to a log as log files for this script.