Scanner le réseau à la recherche d’instances SQL Server

Scanner le réseau pour y retrouver les instances SQL Server installés peut être tâche ardue selon le contexte où l’on se trouve. Il existe bien la commande sqlcmd -L mais celles-ci comportent bien des défauts. En effet cet utilitaire lance un broadcast sur le réseau sur lequel il se trouve et attend la réponse des instances qu’il a pu atteindre. J’insiste bien sur la dernière partie de cette phrase « a pu atteindre ». Il existe bien des cas où aucune réponse ne sera retournée : l’instance SQL est cachée ou encore le service SQL Browser n’est pas activé et des instances nommées écoutent sur un port différent que le port 1433 ou encore d’autres sous réseaux ne peuvent pas être atteint par la requête broadcast etc … bref autant de raisons qui font que l’utilisation de sqlcmd n’est pas forcément judicieuse dans ce cas. Voici un script powershell qui permet de recenser l’ensemble des instances SQL beaucoup plus précisement que la commande sqlcmd ou autre méthode utilisant ce principe.

L’idée est la suivante :

  • On se base sur l’annuaire Active Directory pour lister l’ensemble des ordinateurs dans le domaine
  • On vérifie pour chaque serveur si un service associé à SQL Server existe (instance par défaut ou instance nommée)

 

# CLEAR CONSOLE
CLS;

# CURRENT DOMAIN
$domain = [system.directoryservices.activedirectory.domain]::GetCurrentDomain();
# PATH FILE TO WRITE RESULT
$pathresult = « .\result_discovery_sqlserver.txt »;
# PATH FILE TO WRITE ERRORS
$patherror = « .\error_discovery_sqlserver.txt »;

Write-Progress -activity « Scan SQL Server instances into the domain : $domain » -status  » –> In progress »;
Write-Host «  »;
Write-Host «  »;
Write-Host «  »;
Write-Host «  »;
Write-Host «  »;
Write-Host «  »;
Write-Host «  »;
Write-Host «  »;

 
[System.reflection.assembly]::loadwithpartialname(« System.DirectoryServices.dll »)

$objDomain = New-Object System.DirectoryServices.DirectoryEntry(« LDAP://$domain »)

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = (« (ObjectClass=Computer) »)

$Computers = $objSearcher.FindAll()

# RESET FILES CONTENT
out-file $pathresult;
out-file $patherror;

# DISCOVER FOR EACH COMPUTER IF EXIST ONE OR SEVERAL SQL SERVER INSTANCES
# BY CHECKING THE SQL SERVICES
Foreach ($entry in $Computers)
{
$computer = $entry.GetDirectoryEntry();
 
try
{
  $sql_server = get-wmiobject -class win32_service -computer $computer.Name -EA STOP

  $instances = $sql_server | where { $_.name -like ‘MSSQL$*’ -or $_.name -eq ‘MSSQLSERVER’ } | Select -Property Name
 
  Foreach ($instance_name in $instances)
  {
   $list_instance +=  »  » + $instance_name.Name;
  }

  If ($instances.Count -gt 0)
  {
   $line = $Computer.Name,$list_instance -join «  »;
   # WRITE TO CONSOLE
   Write-Host $line.replace( » « , « , »);
 
   # WRITE TO FILE
   $line.replace( » « , « , ») | out-file $pathresult -append;
  }
}
catch
{
  $computer.Name | Out-File $patherror -append;
  $_ | Out-File $patherror -append;
  «  » | Out-File $patherror -append;
}

$list_instance = «  »;
}

Write-Host «  »;
Write-Host « Done… » -foreground green;
Write-Host «  »;
Start-Sleep -s 2;

 

Bien entendu cette méthode est loin d’être parfaite et nécessite des privilèges assez élevés pour fonctionner :

  • Pouvoir lire l’annuaire Active Directory
  • Avoir les droits administrateur local sur chaque serveur pour pouvoir utiliser la couche WMI.

Autant dire qu’il faudra donner cela à un administrateur du domaine si vous voulez être tranquille mais bon lorsque l’on veut faire un inventaire on n’a souvent pas le choix Smile . N’hésitez pas à me faire remonter vos feedbacks  !!

Bon inventaire d’instances SQL Server !!

David BARBARIN (Mikedavem)
MVP SQL Server

Laisser un commentaire