Advertisement
Guest User

Untitled

a guest
Oct 31st, 2017
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VBScript 12.24 KB | None | 0 0
  1. ' -----------------------------------------------------------------------------
  2. ' Check_MK windows agent plugin to gather information from local MSSQL servers
  3. '
  4. ' This plugin can be used to collect information of all running MSSQL server
  5. ' on the local system.
  6. '
  7. ' The current implementation of the check uses the "trusted authentication"
  8. ' where no user/password needs to be created in the MSSQL server instance by
  9. ' default. It is only needed to grant the user as which the Check_MK windows
  10. ' agent service is running access to the MSSQL database.
  11. '
  12. ' Another option is to create a mssql.ini file in MK_CONFDIR and write the
  13. ' credentials of a database user to it which shal be used for monitoring:
  14. '
  15. ' [auth]
  16. ' type = db
  17. ' username = monitoring
  18. ' password = secret-pw
  19. '
  20. ' The following sources are asked:
  21. ' 1. WMI - to gather a list of local MSSQL-Server instances
  22. ' 2. MSSQL-Servers via ADO/sqloledb connection to gather infos these infos:
  23. '      a) list and sizes of available databases
  24. '      b) counters of the database instance
  25. '
  26. ' This check has been developed with MSSQL Server 2008 R2. It should work with
  27. ' older versions starting from at least MSSQL Server 2005.
  28. ' -----------------------------------------------------------------------------
  29.  
  30. Option Explicit
  31.  
  32. Dim WMI, FSO, SHO, items, objItem, prop, instId, instIdx, instVersion
  33. Dim instIds, instName, output, isClustered, instServers
  34. Dim WMIservice, colRunningServices, objService, cfg_dir, cfg_file, hostname
  35.  
  36. ' Directory of all database instance names
  37. Set instIds = CreateObject("Scripting.Dictionary")
  38. Set FSO = CreateObject("Scripting.FileSystemObject")
  39. Set SHO = CreateObject("WScript.Shell")
  40.  
  41. hostname = SHO.ExpandEnvironmentStrings("%COMPUTERNAME%")
  42. cfg_dir = SHO.ExpandEnvironmentStrings("%MK_CONFDIR%")
  43.  
  44. output = ""
  45. Sub addOutput(text)
  46.     output = output & text & vbLf
  47. End Sub
  48.  
  49. Function readIniFile(path)
  50.     Dim parsed : Set parsed = CreateObject("Scripting.Dictionary")
  51.     If path <> "" Then
  52.         Dim FH
  53.         Set FH = FSO.OpenTextFile(path)
  54.         Dim line, sec, pair
  55.         Do Until FH.AtEndOfStream
  56.             line = Trim(FH.ReadLine())
  57.             If Left(line, 1) = "[" Then
  58.                 sec = Mid(line, 2, Len(line) - 2)
  59.                 Set parsed(sec) = CreateObject("Scripting.Dictionary")
  60.             Else
  61.                 If line <> "" Then
  62.                     pair = Split(line, "=")
  63.                     If 1 = UBound(pair) Then
  64.                         parsed(sec)(Trim(pair(0))) = Trim(pair(1))
  65.                     End If
  66.                 End If
  67.             End If
  68.         Loop
  69.         FH.Close
  70.     End If
  71.     Set readIniFile = parsed
  72. End Function
  73.  
  74. ' Detect whether or not the script is called in a clustered environment.
  75. ' Saves the virtual server names of the DB instances
  76. Set instServers = CreateObject("Scripting.Dictionary")
  77. On Error Resume Next
  78. Set WMI = GetObject("WINMGMTS:\\.\root\mscluster")
  79. Set items = WMI.execQuery("SELECT Name, Status, State, Type, PrivateProperties " & _
  80.                           "FROM MsCluster_Resource WHERE Type = 'SQL Server'")
  81. For Each objItem in items
  82.     instName = objItem.PrivateProperties.InstanceName
  83.     instServers(instName) = objItem.PrivateProperties.VirtualServerName
  84. Next
  85.  
  86. If Err.Number <> 0 Then
  87.     Err.Clear()
  88.     isClustered = FALSE
  89. Else
  90.     isClustered = TRUE
  91. End If
  92. On Error Goto 0
  93.  
  94. ' Dummy empty output.
  95. ' Contains timeout error if this scripts runtime exceeds the timeout
  96. WScript.echo "<<<mssql_versions>>>"
  97.  
  98. ' Loop all found local MSSQL server instances
  99. ' Try different trees to handle different versions of MSSQL
  100. On Error Resume Next
  101. ' try SQL Server 2016:
  102. Set WMI = GetObject("WINMGMTS:\\.\root\Microsoft\SqlServer\ComputerManagement13")
  103. If Err.Number <> 0 Then
  104.     Err.Clear()
  105.     ' try SQL Server 2014:
  106.     Set WMI = GetObject("WINMGMTS:\\.\root\Microsoft\SqlServer\ComputerManagement12")
  107.     If Err.Number <> 0 Then
  108.         Err.Clear()
  109.         ' try SQL Server 2012:
  110.         Set WMI = GetObject("WINMGMTS:\\.\root\Microsoft\SqlServer\ComputerManagement11")
  111.         If Err.Number <> 0 Then
  112.             Err.Clear()
  113.  
  114.             ' try SQL Server 2008
  115.             Set WMI = GetObject("WINMGMTS:\\.\root\Microsoft\SqlServer\ComputerManagement10")
  116.             If Err.Number <> 0 Then
  117.                 Err.Clear()
  118.  
  119.                 ' try MSSQL < 10
  120.                 Set WMI = GetObject("WINMGMTS:\\.\root\Microsoft\SqlServer\ComputerManagement")
  121.                 If Err.Number <> 0 Then
  122.                     WScript.echo "Error: " & Err.Number & " " & Err.Description
  123.                     Err.Clear()
  124.                     wscript.quit()
  125.                 End If
  126.             End If
  127.         End If
  128.     End If
  129. End If
  130. On Error Goto 0
  131.  
  132. Set WMIservice = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  133.  
  134. For Each prop In WMI.ExecQuery("SELECT * FROM SqlServiceAdvancedProperty WHERE " & _
  135.                                "SQLServiceType = 1 AND PropertyName = 'VERSION'")
  136.  
  137.  
  138.     Set colRunningServices = WMIservice.ExecQuery("SELECT State FROM Win32_Service " & _
  139.                                                   "WHERE Name = '" & prop.ServiceName & "'")
  140.     instId      = Replace(prop.ServiceName, "$", "__")
  141.     instVersion = prop.PropertyStrValue
  142.     instIdx = Replace(instId, "__", "_")
  143.     addOutput( "<<<mssql_versions>>>" )
  144.     addOutput( instIdx & "  " & instVersion )
  145.  
  146.     ' Now query the server instance for the databases
  147.    ' Use name as key and always empty value for the moment
  148.    For Each objService In colRunningServices
  149.         If objService.State = "Running" Then
  150.             instIds.add instId, ""
  151.         End If
  152.     Next
  153. Next
  154.  
  155. Set WMI = nothing
  156.  
  157. Dim CONN, RS, CFG, AUTH
  158.  
  159. ' Initialize connection objects
  160. Set CONN = CreateObject("ADODB.Connection")
  161. Set RS = CreateObject("ADODB.Recordset")
  162. CONN.Provider = "sqloledb"
  163.  
  164. ' Loop all found server instances and connect to them
  165. ' In my tests only the connect using the "named instance" string worked
  166. For Each instId In instIds.Keys
  167.     ' Use either an instance specific config file named mssql_<instance-id>.ini
  168.    ' or the default mysql.ini file.
  169.    cfg_file = cfg_dir & "\mssql_" & instId & ".ini"
  170.     If Not FSO.FileExists(cfg_file) Then
  171.         cfg_file = cfg_dir & "\mssql.ini"
  172.         If Not FSO.FileExists(cfg_file) Then
  173.             cfg_file = ""
  174.         End If
  175.     End If
  176.  
  177.     Set CFG = readIniFile(cfg_file)
  178.     If Not CFG.Exists("auth") Then
  179.         Set AUTH = CreateObject("Scripting.Dictionary")
  180.     Else
  181.         Set AUTH = CFG("auth")
  182.     End If
  183.  
  184.     ' At this place one could implement to use other authentication mechanism
  185.    If Not AUTH.Exists("type") or AUTH("type") = "system" Then
  186.         CONN.Properties("Integrated Security").Value = "SSPI"
  187.     Else
  188.         CONN.Properties("User ID").Value = AUTH("username")
  189.         CONN.Properties("Password").Value = AUTH("password")
  190.     End If
  191.  
  192.     If InStr(instId, "__") <> 0 Then
  193.         instName = Split(instId, "__")(1)
  194.     instId = Replace(instId, "__", "_")
  195.     Else
  196.         instName = instId
  197.     End If
  198.  
  199.     ' In case of instance name "MSSQLSERVER" always use (local) as connect string
  200.    If Not isClustered Then
  201.         If instName = "MSSQLSERVER" Then
  202.             CONN.Properties("Data Source").Value = "(local)"
  203.         Else
  204.             CONN.Properties("Data Source").Value = hostname & "\" & instName
  205.         End If
  206.     Else
  207.         ' In case the instance name is "MSSQLSERVER" always use the virtual server name
  208.        If instName = "MSSQLSERVER" Then
  209.             CONN.Properties("Data Source").Value = instServers(instName)
  210.         Else
  211.             CONN.Properties("Data Source").Value = instServers(instName) & "\" & instName
  212.         End If
  213.     End If
  214.  
  215.     CONN.Open
  216.  
  217.     ' Get counter data for the whole instance
  218.    RS.Open "SELECT counter_name, object_name, instance_name, cntr_value " & _
  219.             "FROM sys.dm_os_performance_counters " & _
  220.             "WHERE object_name NOT LIKE '%Deprecated%'", CONN
  221.     addOutput( "<<<mssql_counters>>>" )
  222.     Dim objectName, counterName, instanceName, value
  223.     Do While NOT RS.Eof
  224.         objectName   = Replace(Replace(Trim(RS("object_name")), " ", "_"), "$", "_")
  225.         counterName  = LCase(Replace(Trim(RS("counter_name")), " ", "_"))
  226.         instanceName = Replace(Trim(RS("instance_name")), " ", "_")
  227.         If instanceName = "" Then
  228.             instanceName = "None"
  229.         End If
  230.         value        = Trim(RS("cntr_value"))
  231.         addOutput( objectName & " " & counterName & " " & instanceName & " " & value )
  232.         RS.MoveNext
  233.     Loop
  234.     RS.Close
  235.  
  236.     RS.Open "SELECT session_id, wait_duration_ms, wait_type, blocking_session_id " & _
  237.             "FROM sys.dm_os_waiting_tasks " & _
  238.             "WHERE blocking_session_id <> 0 ", CONN
  239.     addOutput( "<<<mssql_blocked_sessions>>>" )
  240.     Dim session_id, wait_duration_ms, wait_type, blocking_session_id
  241.     Do While NOT RS.Eof
  242.         session_id = Trim(RS("session_id"))
  243.         wait_duration_ms = Trim(RS("wait_duration_ms"))
  244.         wait_type = Trim(RS("wait_type"))
  245.         blocking_session_id = Trim(RS("blocking_session_id"))
  246.         addOutput( session_id & " " & wait_duration_ms & " " & wait_type & " " & blocking_session_id  )
  247.         RS.MoveNext
  248.     Loop
  249.     RS.Close
  250.  
  251.     ' First only read all databases in this instance and save it to the db names dict
  252.    RS.Open "EXEC sp_databases", CONN
  253.     Dim x, dbName, dbNames
  254.     Set dbNames = CreateObject("Scripting.Dictionary")
  255.     Do While NOT RS.Eof
  256.         dbName = RS("DATABASE_NAME")
  257.         dbNames.add dbName, ""
  258.        RS.MoveNext
  259.     Loop
  260.     RS.Close
  261.  
  262.     ' Now gather the db size and unallocated space
  263.    addOutput( "<<<mssql_tablespaces>>>" )
  264.     Dim i, dbSize, unallocated, reserved, data, indexSize, unused
  265.     For Each dbName in dbNames.Keys
  266.         ' Switch to other database and then ask for stats
  267.        RS.Open "USE [" & dbName & "]", CONN
  268.         ' sp_spaceused is a stored procedure which returns two selects
  269.        ' which need to be looped
  270.        RS.Open "EXEC sp_spaceused", CONN
  271.         i = 0
  272.         Do Until RS Is Nothing
  273.             Do While NOT RS.Eof
  274.                 'For Each x in RS.fields
  275.                '    wscript.echo x.name & " " & x.value
  276.                'Next
  277.                If i = 0 Then
  278.                     ' Size of the current database in megabytes. database_size includes both data and log files.
  279.                    dbSize      = Trim(RS("database_size"))
  280.                     ' Space in the database that has not been reserved for database objects.
  281.                    unallocated = Trim(RS("unallocated space"))
  282.                 Elseif i = 1 Then
  283.                     ' Total amount of space allocated by objects in the database.
  284.                    reserved    = Trim(RS("reserved"))
  285.                     ' Total amount of space used by data.
  286.                    data        = Trim(RS("data"))
  287.                     ' Total amount of space used by indexes.
  288.                    indexSize   = Trim(RS("index_size"))
  289.                     ' Total amount of space reserved for objects in the database, but not yet used.
  290.                    unused      = Trim(RS("unused"))
  291.                 End If
  292.                 RS.MoveNext
  293.             Loop
  294.             Set RS = RS.NextRecordset
  295.             i = i + 1
  296.         Loop
  297.         addOutput( instId & " " & Replace(dbName, " ", "_") & " " & dbSize & " " & unallocated & " " & reserved & " " & _
  298.                      data & " " & indexSize & " " & unused )
  299.         Set RS = CreateObject("ADODB.Recordset")
  300.     Next
  301.  
  302.     ' Loop all databases to get the date of the last backup. Only show databases
  303.    ' which have at least one backup
  304.    Dim lastBackupDate
  305.     addOutput( "<<<mssql_backup>>>" )
  306.     For Each dbName in dbNames.Keys
  307.         RS.open "SELECT CONVERT(VARCHAR, DATEADD(s, DATEDIFF(s, '19700101', MAX(backup_finish_date)), '19700101'), 120) AS last_backup_date " & _
  308.                 "FROM msdb.dbo.backupset " & _
  309.                 "WHERE database_name = '" & dbName & "'", CONN
  310.         Do While Not RS.Eof
  311.             lastBackupDate = Trim(RS("last_backup_date"))
  312.             If lastBackupDate <> "" Then
  313.                 addOutput( instId & " " & Replace(dbName, " ", "_") & " " & lastBackupDate )
  314.             End If
  315.             RS.MoveNext
  316.         Loop
  317.         RS.Close
  318.     Next
  319.  
  320.     CONN.Close
  321. Next
  322.  
  323. Set RS = nothing
  324. Set CONN = nothing
  325. Set FSO = nothing
  326. Set SHO = nothing
  327.  
  328. ' finally output collected data
  329. WScript.echo output
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement