Pessoal,
Nos meus scripts powershell eu tenho um txt contendo o nome dos servidores que irei coletar os dados. É assim :
Server1
Server2
Server2\Instance1
Server3
Este txt é gravado em um folder.Com base nele que eu coleto todas as informações que eu preciso.
Tá mas se o servidor estiver fora ou o serviço do sql server estiver offline ?
Pra isso eu criei duas funções a get-ping e a get-servicesql que primeiramente testa o ping e depois testa o serviço do sql server.
A get-servicesql é bem legal pois ela divide o nome da instancia do nome do servidor e testa o serviço correspondente.
Por exemplo instancia default o nome do serviço é MSSQLSERVER, para uma nomeada digamos instancia1 é MSSQLSERVER$instancia1.
Intaum o fluxo é este nos meus scripts.
1 – Carrego o nome do servidor
2 – Separo o Nome do servidor do nome da instancia
3 – Pingou o servidor ?
4 – Se pingou vou para 5 senão logo (save-log) e volto pra 1
5 – Testo o servico da instancia
6 – Esta online vou para 7 senão logo (save-log) e volto pra 1
7 – carrego uma variavel com o nome dos servidores ok (server1,server2,server3)
Após isso, faço a coleta de dados com base nesta variavel.
vamos aos scripts ?..Está em inglês (nao reparem ele por sinal), pois estou escrevendo um artigo pra um site gringo.
##########################################################
#Save a log in path
#Funcao pra salvar log
##########################################################
Function Save-Log ([String] $NamePS1,
[String] $Server,
[String] $Erro,
[String] $PathFileError
)
{
#test if path wich will contains the error file exists. if not create
if (!(Test-Path -path $PathFileError))
{
New-Item $PathFileError
}
#Put the name of error file like $Nameps1.log
$NameFileFull = $PathFileError + "\" + $NamePS1 + (get-date -format "yyyyMMddhhmmss") + ".log"
if (Test-Path -path $NameFileFull)
{
del $NameFileFull -ErrorAction "silentlycontinue"
}
$date = get-date -format "yyyy-MM-dd hh:mm:ss"
"Server : " + $Server, "Date : " + $date ,"Error Message: " + $Erro | Out-file $NameFileFull -append
}
##########################################################
#Retrive the Server name in Fullservername
#If $Fullservername = "server\instance1" returns server1
#Função para separa o nome do servidor da string "server\instance"
##########################################################
Function get-servername ([string] $FullServerName)
{
if (!($FullServerName.contains("\")))
{ Return $FullServerName }
$Position = $FullServerName.indexof("\")
$ServerName = $FullServerName.substring(0,$Position)
return $ServerName
}
##########################################################
#Retrive the Instance name in Fullservername
#If $Fullservername = "server\instance1" returns instance1
#Função para separa o nome do instancia da string "server\instance"
##########################################################
Function get-instance ([string] $FullServerName)
{
if (!($FullServerName.contains("\")))
{ Return "" }
$Position = $FullServerName.indexof("\")
$InstanceName = $FullServerName.substring($Position+1)
return $InstanceName
}
##########################################################
#Function to verify if sql server service is active
# Função para testar o serviço do sql server nos servidores (locais e remotos)
# Veja que para instancia default testo MSSQLSERVER senao testo MSSQLSERVER$NOmedaInstancia
##########################################################
Function get-servicesql ([string] $FullNomeservidor)
{
$ServerName = ""
$InstanceName = ""
# Divide the servername and instance name
$ServerName = get-servername $FullNomeservidor
$InstanceName = get-instance $FullNomeservidor
# If have a instance name i get MSSQL$Instancename Otherwise MSSQLSERVER (default)
$ServiceName = "MSSQL$" + $InstanceName
if ( $InstanceName -eq "" -or $InstanceName -eq $Null)
{ $ServiceName = "MSSQLSERVER" }
$Check = get-wmiobject win32_service -computername $ServerName -ErrorAction silentlyContinue |where-object {($_.name -like $ServiceName)}
if (!$?)
{
$Erro = "Server " + $ServerName + " Instance " + $InstanceName + " not avaliable"
Save-Log Service $ServerName $Erro "C:\Project\Log"
}
Return ($Check.state -eq "Running")
}
##########################################################
#Ping Server Function
#Função para pingar o servidor
##########################################################
Function get-ping ([String] $FullServerName)
{
$ServerName = ""
$ServerName = get-servername $FullServerName
$Check = get-wmiobject win32_pingstatus -Filter "Address=’$ServerName’" -ErrorAction silentlyContinue | Select-Object statuscode
if (!$?)
{
$Erro = "Server " + $ServerName + " Not Avaliable in Ping !!! "
Save-Log Ping $ServerName $Erro "C:\Project\Log"
}
return ($Check.statuscode)
}
#Scripst de Coleta
#First i get the server and database repository name
# Carrego o nome do meu repositorio de dados (servidor e database)
$Repository = get-content "C:\Project\Configuration\repository.txt"
$Repository = $Repository.split(",")
$ServerRepository = $Repository[0]
$DatabaseRepository = $Repository[1]
#Now i get the Servers and test ping and if the MSSQL Service is ok. If not, its logged in folder C:\Project\Log
# and set the variable to wich server i will not collect the data
#Aqui eu faço os testes e carrego a variavel
$ServersAvaliable = ""
foreach ($svr in get-content "C:\servers\servers.txt" )
{
#test ping
if ((get-ping $svr) -eq 0)
{
#Test service
if ((get-ServiceSql $svr) -eq $True)
{
$ServersAvaliable = $ServersAvaliable + $svr + ","
}
else
{
$Erro = "Service in Server " + $svr +" not avaliable in Get-Service !!!"
Save-Log "CollectInfo" $svr $Erro "C:\Project\Log"
}
}
else
{
$Erro = "Server " + $svr + " Not Avaliable in Get-Ping !!! "
Save-Log "CollectInfo" $svr $Erro "C:\Project\Log"
}
}
# take off last comma
# Tiro a ultima virgula pois a string fica (server1,server2,server3,)
$ServersAvaliable = $ServersAvaliable.Substring(0,$ServersAvaliable.Length -1)
#Now, these are the servers that I will check
#Dou o split e mando pra uma array
$ServersAvaliable = $ServersAvaliable.Split(",")
#Agora é so andar nos servidores da array pois são estes que estão online
$Total = $ServersAvaliable.Count – 1
$Count = 0
for(;$Count -le $Total;$Count++)
{
#Anda na variavel com os servidores online
#Coleto os dados
}
Sempre lembrando que não preciso ter o powershell instalado nos servidores, somente no que vai rodar o script, seja ele o minishell do sql server 2008 ou o própio powershell.
Este script serve para todos as versões do sql server, pos não utilizo a SMO nele.
É isso aí..abraços
I´ll be back



