PowerShell e o dia a dia do DBA – Testando Linked Servers – UMA ABORDAGEM PROFISSIONAL


 

Pessoal,

Um amigo meu me perguntou se ele poderia usar este script de linked server no ambiente dele (ele me perguntou assim : e se um de meus servidores estiver off de proposito,..ou um serviço parado de propósito..nao pode testar). Eu disse que sim, mas como estes script estão sem tratamento de erros (pois no meu ambiente eu tenho o controle do que posso estar checando), resolvi até para eu não ter que me preocupar se o servidor esta pingando.serviço rodando para testar os linked servers, eu montei uma abordagem mais PROFISIONAL da coisa. Usando funções, tratamento de erro e um arquivo de LOG.

Vou Falar sobre as funções primeiro. Eu as criei num arquivo chamado funcoes.ps1

##########################################################
#Função para Salvar o LOG
##########################################################

Function Salva-Log ([String] $NamePS1,
                  [String] $Server,
                  [String] $Error,
                  [String] $PathFileError
                 )
{

  #Testa se o path que vai ter o arquivo de erro existe..senão cria…pode se tirar esta checagem com o #
  if (!(Test-Path -path $PathFileError))
  {
    New-Item $PathFileError
  }

  #Assume o arquivo de log como sendo o nome do ps1 + data + .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"
  "Servidor : " + $Server, "Data : " + $date ,"Mensagem de Erro : " + $Error | Out-file  $NameFileFull -append

}

##########################################################
#Função para retirar somente o nome do servidor Eu Faço isso pois no txt pode vir como servidor\instancia e pro ping e pra testar o #serviço eu preciso deles separados
##########################################################

Function get-servidor ([string] $NomeServidor)
{
   if (!($nomeservidor.contains("\")))
   { Return $NomeServidor }

   $posicao = $nomeservidor.indexof("\")

   $NomeServidor = $NomeServidor.substring(0,$posicao)
   return $NomeServidor
}

##########################################################
#Função para retirar somente o nome da instancia.Eu Faço isso pois no txt pode vir como servidor\instancia e pro ping e pra testar o #serviço eu preciso deles separados
##########################################################

Function get-Instancia ([string] $NomeServidor)
{
   if (!($nomeservidor.contains("\")))
   { Return $NomeServidor }

   $posicao = $nomeservidor.indexof("\")

   $NomeServidor = $NomeServidor.substring($posicao+1)
   return $NomeServidor
}

##########################################################
#Função para verificar se o serviço do sql server está ativo. Detalhe se tiver instancia ele testa o servico MSSQL$Instancia..senao #somente MSSQL*
##########################################################
Function get-servicosql ([string] $FullNomeservidor)
{

   $NomeServidor = ""
   $NomeInstancia = ""

# divido o nome da instancia do servidor se tiver

   $NomeServidor = get-servidor $FullNomeservidor
   $NomeInstancia = get-instancia $FullNomeservidor

   $NomeServico = "MSSQL$" + $NomeInstancia

# se tiver instancia pego MSSQL$NomeInstancia senao pego MSSQL*

   if ( $NomeInstancia -eq "" -or $NomeInstancia -eq $Null)
      {    $nomeServico = "MSSQL*" }

    $Check = get-wmiobject win32_service -computername $Nomeservidor -ErrorAction silentlyContinue |where-object {($_.name -eq $nomeServico)}
    if (!$?)
    {  
      $Erro = "Ocorreu um erro tentando checar o serviço do sql em " + $NomeServidor + " Instancia " + $NomeInstancia
      Salva-Log TestLinkedServerError $NomeServidor $Erro "C:\dadosps"
    }
    Return ($Check.state -eq "Running")
}

##########################################################
#Função para Pingar o Servidor
##########################################################
Function get-Ping ([String] $FullNomeservidor)
{
    $NomeServidor = ""
    $NomeServidor = get-servidor $FullNomeservidor
    $Check = get-wmiobject win32_pingstatus -Filter "Address=’$NomeServidor’" -ErrorAction silentlyContinue | Select-Object statuscode
    if (!$?)
    {  
      $Erro = "Ocorreu um erro tentando Pingar em " + $NomeServidor + "  !!!  "
      Salva-Log TestLinkedServerError $NomeServidor $Erro "C:\dadosps"
    }

    return ($Check.statuscode)
}

 

Pronto…Agora o arquivo que testa os linked servers eu o chamei de TestLinkedServerErro.ps1

Param (    [string] $ServidorCentral,
    [String] $DatabaseCentral,
        [String] $FullPathFileTXTServers #Nome do TXT de servidores
      )

#Aqui eu carrego o arquivo de funçoes

\Palestras\Interoperabilidade\CheckList\funcoes.ps1

[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null

#estao comentados para testes, pois passeramos estes parametros na chamada do ps1

#$ServidorCentral = "SERVER1\MSSQLSERVER_1"
#$DatabaseCentral = "DBA"
#$FullPathFileTXTServers = "C:\dadosps\servidores.txt"

##########################################################
#Testa se os parametros vieram com informação
##########################################################

if ($ServidorCentral -eq "" -or $ServidorCentral -eq $Null)
{
      $Erro = "Informe o Servidor Central !!!"
      write-host $erro
      exit
}

if ($DatabaseCentral -eq "" -or $DatabaseCentral -eq $Null)
{
      $Erro = "Informe o Databse Central !!!"
      write-host $erro
      exit
}

if ($FullPathFileTXTServers -eq "" -or $FullPathFileTXTServers -eq $Null)
{
      $Erro = "Informe o Caminho/Arquivo dos Servidores !!!"
      write-host $erro
      exit
}

##########################################################
#Carrega os servidores
##########################################################
$Servidores = get-content $FullPathFileTXTServers -ErrorAction "silentlycontinue"
if (!$?)
   {  
      $Erro = "Verifique o Path/arquivo de configuração dos servidores !!!  – " + $FullPathFileTXTServers
      write-host $erro
      exit
   }

$datas = get-date -format "yyyy-MM-dd hh:mm:ss"
$Erro = ""

$sql = "truncate table diario.tb_LinkeDServersErro"
Invoke-Sqlcmd -ServerInstance $ServidorCentral -Database $DatabaseCentral -Query $sql -ErrorAction silentlyContinue
if (!$?)
   {  
      $Erro = "Verifique Se o Servidor Central/Database/Tabela existem  !!! "
      Salva-Log TestLinkedServerError Erro $Erro "C:\dadosps"
      exit;
   }

foreach ($svr in $servidores)
{

#Faço o teste de Ping se deu pau eu logo no arquivo de log

   if ((get-ping $svr) -eq 0)
   {

# só faço o teste de linked servers para os servers que estiverem com o serviço ativo   se estiver parado eu logo

       if ((get-servicosql $svr) -eq $True)
       {

#tudo certo..testo os linked servers
    $Serv =New-Object "Microsoft.SqlServer.Management.Smo.Server" "$svr"
    $data = $Serv.linkedservers| where-object {$_.State -eq "Existing"} | foreach {
             trap [Exception] {
                 $erro =  $_.Exception.Message
                 $sql1 = "set dateformat dmy insert into diario.tb_LinkedServersErro(servidor,data,NomeLinkedServer,msgerro) values (‘$svr’,’$datas’,’$NomeLinkedServer’,’$erro’)"
                 Invoke-Sqlcmd -ServerInstance $ServidorCentral -Database $DatabaseCentral -Query $sql1
                 continue;
             }
             $NomeLInkedServer = $_.name
             $_.testconnection()
             }

        }
        else
        {
           $Erro = "Serviço do sql " + $svr + " Parado !!! "
           Salva-Log TestLinkedServerError Erro $Erro "C:\dadosps"
        }
    }
    else
    {
       $Erro = "Servidor não respondendo ao ping " + $svr
       Salva-Log TestLinkedServerError Erro $Erro "C:\dadosps"
    }

}

 

Pronto….desta maneira a coisa fica mais profissional e podemos usar  com os devidos tratamentos de erros.

Para Executa-lo

 

\Palestras\Interoperabilidade\CheckList TestLinkedServerErro.ps1 Server1\MSSQLSERVER_1 DBA c:\dadosps\servidores.txt

Aonde 

Server1\MSSQLSERVER_1 é o servidor Central

 DBA  o Banco Central

c:\dadosps\servidores.txt caminho e nome do txt de servidores

 

 

 

Abraços

About Laerte Junior

Laerte Junior Laerte Junior is a SQL Server specialist and an active member of WW SQL Server and the Windows PowerShell community. He also is a huge Star Wars fan (yes, he has the Darth Vader´s Helmet with the voice changer). He has a passion for DC comics and living the simple life. "May The Force be with all of us"
This entry was posted in Powershell. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s