需求描述
在我們的生產(chǎn)環(huán)境中,大部分情況下需要有自己的運(yùn)維體制,包括自己健康狀態(tài)的檢測等。如果發(fā)生異常,需要提前預(yù)警的,通知形式一般為發(fā)郵件告知。
在所有的自檢流程中最基礎(chǔ)的一個就是磁盤剩余空間檢測。作為一個高效的DBA不可能每天都要上生產(chǎn)機(jī)上查看磁盤剩余或者直到磁盤無剩余空間報錯后才采取擴(kuò)容措施。
當(dāng)然,作為微軟的服務(wù)器有著自己的監(jiān)控軟件:SCCM(System Center Configuration Manager)。但本篇就介紹如果通過Power shell實(shí)現(xiàn)狀態(tài)值監(jiān)控,相比SCCM更輕量級和更具靈活性。
本篇實(shí)現(xiàn)
1、每天檢測磁盤剩余空間大小,如果剩余空間超過了閥值,則發(fā)郵件告訴管理員
2、每天檢測SQL Server運(yùn)行的錯誤日志(Window平臺的錯誤日志),形成郵件附件發(fā)送給管理員
監(jiān)控腳本
首先我們來解決第一個問題,關(guān)于磁盤剩余空間的問題,對于磁盤的監(jiān)控的存在兩個需要解決的問題:
<1>一般監(jiān)控我們需要監(jiān)控很多臺服務(wù)器的磁盤,所以對于服務(wù)器的量控制我們需要生成一個配置文件。
<computernames>
<computername>
wuxuelei-pc
</computername>
</computernames>
配置文件名字:computername.xml,這樣就解決很多服務(wù)器的問題,只需要在配置文件中增加就可以,因為我在本地測試,所以就配置了我的本地電腦。
<2>對于服務(wù)器的磁盤監(jiān)控也需要定義一個閥值,用來動態(tài)改變,用來定義生成預(yù)警的閥值。簡單點(diǎn)就是定義我們檢測的磁盤剩余空間到了多少了就自動發(fā)郵件提醒。
<Counters>
<Counter alter = "10" operator = "gt" >C:</Counter>
<Counter alter = "10" operator = "gt" >D:</Counter>
<Counter alter = "10" operator = "gt" >E:</Counter>
<Counter alter = "10" operator = "gt" >F:</Counter>
</Counters>
文件名為:alter_disk.xml,我定義了四個盤符:C: D: E: F:
當(dāng)以上四個盤符那個盤符少于10G了就生成郵件預(yù)警。
實(shí)現(xiàn)代碼如下:
$server = "(local)"
$uid = "sa"
$db="master"
$pwd="password"
$mailprfname = "TestMail"
$recipients = ""
$subject = "老大,快去看看這個服務(wù)器的磁盤空間馬上就不夠了!"
$computernamexml = "F:PowerShell發(fā)送郵件computername.xml"
$alter_xml = "F:PowerShell發(fā)送郵件alter_disk.xml"
function GetServerName($xmlpath)
{
$xml = [xml] (Get-Content $xmlpath)
$return = New-Object Collections.Generic.List[string]
for($i = 0;$i -lt $xml.computernames.ChildNodes.Count;$i++)
{
if ( $xml.computernames.ChildNodes.Count -eq 1)
{
$cp = [string]$xml.computernames.computername
}
else
{
$cp = [string]$xml.computernames.computername[$i]
}
$return.Add($cp.Trim())
}
$return
}
function GetAlterCounter($xmlpath)
{
$xml = [xml] (Get-Content $xmlpath)
$return = New-Object Collections.Generic.List[string]
$list = $xml.counters.Counter
$list
}
function CreateAlter($message)
{
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$CnnString ="Server = $server; Database = $db;User Id = $uid; Password = $pwd"
$SqlConnection.ConnectionString = $CnnString
$CC = $SqlConnection.CreateCommand();
if (-not ($SqlConnection.State -like "Open")) { $SqlConnection.Open() }
$cc.CommandText=
" EXEC msdb..sp_send_dbmail
@profile_name = '$mailprfname'
,@recipients = '$recipients'
,@body = '$message'
,@subject = '$subject'
"
$cc.ExecuteNonQuery()|out-null
$SqlConnection.Close();
}
$names = GetServerName($computernamexml)
$pfcounters = GetAlterCounter($alter_xml)
foreach($cp in $names)
{
$p = New-Object Collections.Generic.List[string]
$report = ""
foreach ($pfc in $pfcounters)
{
$b = ""
$counter ="\"+$cp+"LogicalDisk("+$pfc.get_InnerText().Trim()+")% Free Space"
$p.Add($counter)
}
$count = Get-Counter $p
#Write-Host $count.CounterSamples.Count;
for ($i = 0; $i -lt $count.CounterSamples.Count; $i++)
{
$v = $count.CounterSamples.Get($i).CookedValue
$pfc = $pfcounters[$i]
#$pfc.get_InnerText()
$b = ""
$lg = ""
if ($pfc.operator -eq "gt")
{
if( $v -le [double]$pfc.alter)
{
$b = "alter"
$lg = "Less Than"
}
if($b -eq "alter")
{
$path = "機(jī)器名:"+$cp+"; 盤符:"+$pfc.get_InnerText()
$diskFree="; 當(dāng)前剩余空間為:"+[math]::truncate($v).ToString()+"G;"
$aler=" 超過了你預(yù)定的閥值:"+$pfc.alter.Trim()+"G;速度去處理吧!"
$item = "{0} {1} {2}" -f $path,$diskFree,$aler
$report += $item + "`n"
}
}
}
if($report -ne "")
{
#生產(chǎn)警告 參數(shù) 計數(shù)器,閥值,當(dāng)前值
CreateAlter $report
}
}
通過如上腳本,生成跑批任務(wù),就可以自動的檢測磁盤剩余空間了,而不需要我們?nèi)ナ謩訖z測了。
上述代碼中,有兩個技術(shù)點(diǎn):1、需要自己配置SQL Server郵件代理;2、需要自己配置跑批計劃,方法自己網(wǎng)上搜,很簡單。
效果圖如下
嘿…看到上面的郵件,就是需要聯(lián)系硬件架構(gòu)師,讓其擴(kuò)容或者清除冗余數(shù)據(jù)的時候了。
在上面的腳本中,的確只有我的F盤符超了閥值,所以警報了!
其次,我們來解決第二個問題,關(guān)于SQL Server錯誤日志的問題,作為日常的DBA管理系統(tǒng)中,查看SQL Server錯誤日志是一種常用的方式。當(dāng)然,如果系統(tǒng)運(yùn)行正常,不會產(chǎn)生錯誤日志,一單出現(xiàn)問題,就會生成錯誤日志,但是對于SQL Server錯誤日志會產(chǎn)生很多條,為了方便查找,我們會讓其生成一個文本文件。
以郵件附件的形式,告知管理員,然后管理員就可以通過日志文件快速的定位問題的源頭。
同樣,本篇也是通過computername.xml文件,對多臺服務(wù)器進(jìn)行錯誤日志進(jìn)行篩選
腳本很簡單,如下
$server = "(local)"
$uid = "sa"
$db="master"
$pwd="password"
$mailprfname = "TestMail"
$recipients = ""
$subject = "老大,快去看看這個服務(wù)器的SQL Server出問題了!"
$Info="附件為SQL Server錯誤日志....."
$computernamexml = "F:PowerShell發(fā)送郵件computername.xml"
function GetServerName($xmlpath)
{
$xml = [xml] (Get-Content $xmlpath)
$return = New-Object Collections.Generic.List[string]
for($i = 0;$i -lt $xml.computernames.ChildNodes.Count;$i++)
{
if ( $xml.computernames.ChildNodes.Count -eq 1)
{
$cp = [string]$xml.computernames.computername
}
else
{
$cp = [string]$xml.computernames.computername[$i]
}
$return.Add($cp.Trim())
}
$return
}
function GetAlterCounter($xmlpath)
{
$xml = [xml] (Get-Content $xmlpath)
$return = New-Object Collections.Generic.List[string]
$list = $xml.counters.Counter
$list
}
function CreateAlter($message)
{
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$CnnString ="Server = $server; Database = $db;User Id = $uid; Password = $pwd"
$SqlConnection.ConnectionString = $CnnString
$CC = $SqlConnection.CreateCommand();
if (-not ($SqlConnection.State -like "Open")) { $SqlConnection.Open() }
$cc.CommandText=
" EXEC msdb..sp_send_dbmail
@profile_name = '$mailprfname'
,@recipients = '$recipients'
,@body = '$Info'
,@subject = '$subject'
,@file_attachments='$message'
"
$cc.ExecuteNonQuery()|out-null
$SqlConnection.Close();
}
$names = GetServerName($computernamexml)
foreach($cp in $names)
{
#輸出系統(tǒng)日志中某個特定程序的日志到文件,比如SQL Server,然后選擇錯誤類型為Error
Get-EventLog -ComputerName $cp application | where-object{$_.source-like "MSSQLSERVER"} | where-object{$_.entryType -eq "error"} >F:PowerShell$cp+"SQLErrLog.txt"
#生產(chǎn)警告 參數(shù) 計數(shù)器,閥值,當(dāng)前值
CreateAlter F:PowerShell$cp+"SQLErrLog.txt"
}
效果圖如下
直接下載附件,然后查看錯誤日志就可以了。
該錯誤日志還是挺詳細(xì)的,發(fā)生時間,錯誤明細(xì)等。
(查看大圖)
當(dāng)然,上述腳本還欠缺一點(diǎn)邏輯:
比如:篩選一段時間周期的錯誤日志、或者只查看上次啟動之后的錯誤日志等。
這些邏輯加上也不麻煩,本身PowerShell實(shí)現(xiàn)起來就很簡單。這里就不展開了,自己靈活實(shí)現(xiàn)。
但是,在我們?nèi)粘5姆治鲋校谌罩居涗浂嗟臅r候,用文本分析的方式還是比較慢,通常用Excel查看效果會好很多。
這個實(shí)現(xiàn)也不麻煩,只需要更改腳本如下:
#輸出系統(tǒng)日志中某個特定程序的日志到文件,比如SQL Server,然后選擇錯誤類型為Error
#Get-EventLog -ComputerName $cp application | where-object{$_.source-like "MSSQLSERVER"} | where-object{$_.entryType -eq "error"} >F:PowerShell$cp+"SQLErrLog.txt"
#輸出系統(tǒng)日志中某個特定程序的日志到文件,比如SQL Server,然后選擇錯誤類型為Error,支持Excel打開
Get-EventLog -ComputerName $cp application | where-object{$_.source-like "MSSQLSERVER"} | where-object{$_.entryType -eq "error"} | Export-Clixml –Path F:PowerShell$cp+"SQLErrLog.xml" –Depth 2
#生產(chǎn)警告 參數(shù) 計數(shù)器,閥值,當(dāng)前值
CreateAlter F:PowerShell$cp+"SQLErrLog.xml"
我們下載生成的日志文件,然后打開Excel,然后選擇:數(shù)據(jù)——>從Xml文件導(dǎo)入:
(查看大圖)
如此分析就方便多了。
結(jié)語
本篇就列舉了一下利用PowerShell實(shí)現(xiàn)自動化運(yùn)維和檢測。算作拋磚引玉了吧,自己另有需求可以自己靈活實(shí)現(xiàn)。
關(guān)于SQL Server自動化運(yùn)維和檢測的內(nèi)容很廣泛,其中很多都是從日常的經(jīng)驗中出發(fā),一步步的從手動到自動的過程。
后面的文章,我們將會更深入關(guān)于SQL Server的自動化優(yōu)化運(yùn)維進(jìn)行分析。有興趣的童鞋,可以提前關(guān)注。
更多信息請查看IT技術(shù)專欄