Aujourd'hui il est primordial de mettre à jour ces serveurs Windows, si vous ne souhaitez pas avoir le même problème que certaines sociétés
Source :
https://www.lemagit.fr/etude/Recit-comment-Manutan-sest-sorti-de-la-cyberattaque-du-21-fevrier
que j'ai vu par le site zwinder
https://blog.zwindler.fr/2022/07/30/comment-veulent-ils-que-nous-mettions-a-jour/
Pour cela, j'ai créé deux scripts (du moins 3) qui vont permettre de mettre à jour vos serveurs et de choisir quel jour les redémarrer, mais aussi d'avertir les personnes qui utilisent ces serveurs
Nous allons nous baser sur les besoins suivants
Wsus est un bon produit, mais pas assez personnalisable pour les cas cités précédemment.
Pour le choix numéro 4 - Téléchargement automatique et planification des installations, le redémarrage sera forcement pendant la plage de maintenance.
Sauf dans les cas suivants (si les options sont activées)
Donc si vous activez la planification (option 4) qu'aucun utilisateur n'est connecté et que vous êtes hors de votre plage, votre serveur va redémarrer
C'est pas rassurant sur de la production
Pour améliorer cela, j'ai activé l'option 2 - Notification des téléchargements et des installations et j'ai créé des scripts permettant
Cela corrige donc les problèmes cités ci-dessus
Voici les scripts à adapter selon vos besoins, ils peuvent être améliorés car je ne suis pas expert en powershell
Les scripts sont utilisables de différentes façons
Cela dans le but de permettre une gestion manuelle ou automatique des scripts
Si vous souhaitez automatiser :
(PREPROD,INTE,TEST) équivaut au OU sélectionné
Attention vous devez adapter le fichier OuCharger.ps1 pour indiquer les bons chemins
En manuel :
Conseil :
le script de mise à jour envoie un mail avec les KB installées, ce qui vous permettra de débeugger plus rapidement,
Attention certaines mises à jour pourrait ne pas s'installer car elle serait bloquée par l'une des mises à jour en attente d'un restart
Le script peut être amélioré pour attendre plusieurs heures et remonter les informations des fichiers de logs présent sur les serveurs mise à jour.
Script de téléchargement et installation Windows update
Ligne à modifier :
OU : 49 / 52 / 63 / 66
Modifier les champs des email expediteurs et destinaires mais aussi le relaiSMTP (IP ou DNS) : 215
# Je fais appel à une fonction commune à plusieurs scripts
. ".\OuCharger.ps1"
# Je vide toutes les variables au cas ou elle sont deja utilisées, je met en silencieux les erreurs, car il risque d'indiquer que les varibles n'existe pas
clear-variable -Name "ServeurListe"-ErrorAction SilentlyContinue
clear-variable -Name "ListSRVError" -ErrorAction SilentlyContinue
clear-variable -Name "LogSrvRestart" -ErrorAction SilentlyContinue
clear-variable -Name "LogSrvInstall" -ErrorAction SilentlyContinue
# s'il a un argument, alors je crée la variable manuellement pour la tâche plannifier, le fonctionnement se fera par OU
if ($args[0] -ne $null)
{
$readstart = "ou"
$listConSrv = $args[0]
$listConSrv = $listConSrv.Split(',')
}
#Je met le script en mode debug
$debug = 1
#J'initialise la variable dédiée aux erreurs
$ListSRVError = "Voici la liste des erreurs rencontrées, veuillez vérifier sur les serveurs si cela pourrait être corrigés `n"
$ListSRVError += "`n---------------------------------------------------------------------------------`n`n"
# Vérifie s'il a un argument
if ($args[0] -eq $null)
{
$readstart = Read-Host "OU ou Poste (ou|poste)"
if ($readstart -notmatch "ou|poste")
{
write-host "Veuillez indiquer OU ou POSTE lors de la demande, je quitte"
exit
}
if ($readstart -eq "poste")
{
$ServeurListe = @()
Do{
$StrSrvif = Read-Host "Veuillez indiquer le nom du serveur, si vous souhaitez vous arretez la appuyer sur entrée"
if ($StrSrvif -ne "")
{
$ServeurListe += [pscustomobject]@{Name=$StrSrvif}
}
}Until($StrSrvif -eq "")
}
if ($readstart -eq "ou")
{
Write-Host "OU dispo `n INTE PREPOD PROD TESTING"
$listConSrv = Read-Host "Veuillez indiquer l'OU, si vous en indiquez plusieurs, veuillez mettre des **","** entre chaque OU (sans espace)"
$listConSrv = $listConSrv.Split(',')
if ($listConSrv -notmatch '^INTE$|^PREPOD$|^PROD$|^TESTING$')
{
write-host "Erreur, aucun élément correspondant pour le choix de l'OU (variable listConSrv) en debut de script, Veuillez entrer les bonnes valeurs. Je quitte"
Exit
}
}
}
else
{
if ($readstart -eq "ou")
{
if ($listConSrv -notmatch '^INTE$|^PREPOD$|^PROD$|^TESTING$')
{
write-host "Erreur, L'argument donné lors de l'execution du script ne correspond pas au OU existante."
write-host "Veuillez indiquer une ou plusieurs OU (séparées par une virgule) parmis le choix suivant : INTE PREPROD PROD TESTING"
Exit
}
}
}
# fonction qui permet de concaténer la variable dédiée aux erreurs avec le nom de la machine et l'erreur rencontrée
function ErrReturn ($FuncErr, $FuncErrserveur)
{
$FuncErrorLog += "Serveur : $FuncErrserveur`n"
$FuncErrorLog += "`n---------------------------------------------------------------------------------`n"
$FuncErrorLog += $FuncErr
$FuncErrorLog += "`n---------------------------------------------------------------------------------`n`n"
return $FuncErrorLog
}
# Je vide la variable dédiée aux erreurs pour ne pas avoir les erreurs précédentes
$Error.Clear()
# Je verifie si le module que je souhaite utiliser est bien installé
$ModInstallSrvRoot = Get-Module -ListAvailable -Name PSWindowsUpdate
#Si cela ne retourne pas d'erreur et que la variable est vide alors j'install le module
# Si la variable $ModInstallSrvRoot retourne une erreur alors je l'ajoute dans la variable des erreurs
if (($Error.count -eq 0) -and ($ModInstallSrvRoot -eq $null))
{
#j'installe les paquet requis et charge le module
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module PSWindowsUpdate -Confirm:$false -Force
Import-module PSWindowsUpdate
}
elseif ($Error.count -ne 0)
{
$RootSrvUse = $env:COMPUTERNAME
$ListSRVError += ErrReturn $ErrorFuncSend $RootSrvUse
}
# Suivant les choix effectués, je crée une liste de serveur. J'exclu le nom des OU de la liste pour que ca ne soit pas pris pour un nom de serveur
if ($readstart -eq "ou")
{
# j'utilise la fonction commune à plusieurs script (déclaré en debut de script)
$ServeurListe = OuCharger $listConSrv, $null
}
# J'utilise la liste des serveurs pour faire li'nstallation du module, vérifier les mises à jour et les installer sans restart le serveur
# Le restart des serveurs se fera avec le script PRTG
foreach ($serv in $ServeurListe)
{
if (Test-Connection -ComputerName $serv.Name -Quiet)
{
if ($debug -eq 1)
{
$serv.name
}
$Error.Clear()
$InvokeTest = Invoke-Command -ComputerName $serv.Name -ScriptBlock {Get-Module -ListAvailable -Name PSWindowsUpdate}
if (($Error.count -eq 0) -and ($InvokeTest -eq $null))
{
$Error.Clear()
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force}
if (Select-String -InputObject $Error[0].FullyQualifiedErrorId -Pattern 'NoMatchFoundForProvider' -Quiet)
{
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Set-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319" -Name "SchUseStrongCrypto" -Value "1" -Type DWord}
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319" -Name "SchUseStrongCrypto" -Value "1" -Type DWord}
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force}
$Error.Clear()
}
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Install-Module PSWindowsUpdate -Confirm:$false -Force}
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Import-module PSWindowsUpdate}
sleep 5
$VerifModuleInstall = Invoke-Command -ComputerName $serv.Name -ScriptBlock {Get-Module -ListAvailable -Name PSWindowsUpdate}
if ($VerifModuleInstall -eq $null)
{
$ErrorFuncSend = $Error[0].Exception.message
$ListSRVError += ErrReturn $ErrorFuncSend $serv.Name
Continue
}
}
elseif ($Error.count -ne 0)
{
$ErrorFuncSend = $Error[0].Exception.message
$ListSRVError += ErrReturn $ErrorFuncSend $serv.Name
Continue
}
$Error.Clear()
# Je verifie la liste des mises à jour sur le serveur interrogé, dont les mise à jour exigent le redémarrage
$LstUpdateReq = Get-WindowsUpdate -computername $serv.name
# Si la variable $LstUpdateReq retourne une erreur, je la note et passe au serveur suivant
if ($Error.count -ne 0)
{
$ErrorFuncSend = $Error[0].Exception.message
$ListSRVError += ErrReturn $ErrorFuncSend $serv.Name
Continue
}
# On vérifie les MAJ en ignorant celle qui ont besoin d'un redémarrage
$LstUpdateNotReq = Get-WindowsUpdate -computername $serv.name -IgnoreRebootRequired
if ($LstUpdateReq.count -ne 0)
{
# Je verifie que les mise à jour qui ont besoin d'un redémarrage ne sont pas les même que celle n'ayant pas besoin de redémarrage
if ($LstUpdateReq.count -ne $LstUpdateNotReq.count) {
$LogSrv += "Serveur : " + $serv.Name
$LogSrv += "`n---------------------------------------------------------------------------------`n"
$LogSrv += "############## Mises à jours ayant un besoin de redémarrage du serveur ##############"
$LogSrv += "`n---------------------------------------------------------------------------------`n"
$LogSrv += $LstUpdateReq | Where-Object {$_.KB -notin $LstUpdateNotReq.KB } | Out-String
$LogSrv += "`n---------------------------------------------------------------------------------`n"
$LogSrv += "########################### Installation mise(s) à jour ###########################"
$LogSrv += "`n---------------------------------------------------------------------------------`n"
$LogSrv += Get-WindowsUpdate -computername $serv.name -Install -AcceptAll -Verbose -IgnoreReboot | Out-string
$LogSrv += "`n---------------------------------------------------------------------------------`n"
}
else
{
$LogSrv += "Serveur : " + $serv.Name
$LogSrv += "`n---------------------------------------------------------------------------------`n"
$LogSrv += "########################### Installation mise(s) à jour ###########################"
$LogSrv += "`n---------------------------------------------------------------------------------`n"
$LogSrv += Get-WindowsUpdate -computername $serv.name -Install -AcceptAll -Verbose -IgnoreReboot | Out-string
$LogSrv += "`n---------------------------------------------------------------------------------`n"
}
}
}
else
{
$ErrorFuncSend = "La machine ne repond pas au ping"
$ListSRVError += ErrReturn $ErrorFuncSend $serv.Name
Continue
}
}
# Si l'une des listes n'est pas vide, elle est convertit en caractère. On envoi le mail
if (($LogSrv -ne "") -or ($ListSRVError -ne "")) {
$LogSrv | out-string
$ListSRVError | out-string
if ($debug -eq 1)
{
Write-Host "------------------------------------------- Liste des mise à jours `n $LogSrv `n ------------------------------------------- Serveurs en erreurs `n $ListSRVError `n"
}
else
{
#Encodage UTF8
$encodingMail = [System.Text.Encoding]::UTF8
Send-MailMessage -From "EXPEDITEUR@TONDOM.FR" -To "DESTINATAIRE@TONDOM.FR" -Subject "Rapport des serveurs à restart" -SmtpServer "RELAISMTP(IP ou DNS)" -Body "------------------------------------------- Liste des mise à jour `n $LogSrv `n ------------------------------------------- Serveurs en erreurs `n $ListSRVError `n" -Encoding $encodingMail
}
}
Script PRTG et restart des serveurs
Ligne à modifier :
Chemin du script commun au deux scripts (Mise à jours et restart) : 10
OU : 49 / 57 / 68 / 71
Identifiant et mot de passe PRTG : 108 - 110
Chemin de la liste d'exclusion des serveurs (pour éviter de les restart car trop sensible) : 156
Modifier les champs des email expediteurs et destinaires mais aussi le relaiSMTP (IP ou DNS) : 339
# Je fais appel a une fonction commune aux deux script
. “.\OuCharger.ps1”
#Le mode debug sert à avoir plus d'information, il remplace l'envoi de mail par un affichage dans la console
$debug = 0
#On vide la variable
clear-variable -Name "ServeurListe" -ErrorAction SilentlyContinue
# s'il a un argument, alors je crée le variable manuellement pour la tâche plannifier, le fonctionnement se fera par OU
# l'argument en attente et une ou plusieurs OU séparé par des ,
if ($args[0] -ne $null)
{
$readstart = "ou"
$listConSrv = $args[0]
$listConSrv = $listConSrv.Split(',')
}
if (($debug -ne 1) -and ($debug -ne 0))
{
Write-Host "Veuillez mettre la variable debug à 1 ou 0, je quitte"
exit
}
if ($args[0] -eq $null)
{
$readstart = Read-Host "OU ou Poste (ou|poste)"
if ($readstart -notmatch "ou|poste")
{
write-host "Veuillez indiquer OU ou POSTE lors de la demande, je quitte"
exit
}
if ($readstart -eq "poste")
{
$ServeurListe = @()
Do{
$StrSrvif = Read-Host "Veuillez indiquer le nom du serveur, si vous souhaitez vous arreter la, appuyer sur entrée"
if ($StrSrvif -ne "")
{
$ServeurListe += [pscustomobject]@{Name=$StrSrvif}
}
}Until($StrSrvif -eq "")
}
if ($readstart -eq "ou")
{
Write-Host "OU dispo `n INTE/PREPROD/PROD/TESTING"
$listConSrv = Read-Host "Veuillez indiquer l'OU, si vous en indiquez plusieurs, veuillez mettre des , sans espace"
$listConSrv = $listConSrv.Split(',')
$listConSrv
}
if ($readstart -eq "ou")
{
if ($listConSrv -notmatch '^INTE$|^PREPROD$|^PROD$|^TESTING$')
{
write-host "Erreur, aucun élément correspondant pour le choix de l'OU (variable listConSrv en debut de script), Veuillez entrer les bonnes valeurs. Je quitte"
Exit
}
}
}
else
{
if ($readstart -eq "ou")
{
if ($listConSrv -notmatch '^INTE$|^PREPROD$|^PROD$|^TESTING$')
{
write-host "Erreur, L'argument donné lors de l'execution du script ne correspond pas aux OU existante."
write-host "Veuillez indiquer une ou plusieurs OU séparé par une virgule (si plusieurs) parmis le choix suivant : INTE PREPROD PROD TESTING"
Exit
}
}
}
# Cette fonction permet de créer la tâche plannifier, attention les vieux serveur n'on pas cette fonction powershell
function Task ($SRVName, $TaskTime)
{
$TaskExec= New-ScheduledTaskAction -Execute "shutdown.exe" -Argument "/r /t 0 /f"
$TaskRun = New-ScheduledTaskTrigger -Once -At $TaskTime"pm"
$TaskUser = "NT AUTHORITY\SYSTEM"
Invoke-Command -ComputerName $SRVName -ScriptBlock {Register-ScheduledTask -TaskName $Using:NameTask -Trigger $Using:TaskRun -Action $Using:TaskExec -User $Using:TaskUser -RunLevel Highest –Force -Description "Restart le serveur, car en attente de redemarrage"}
}
# Fonction qui permet d'installer des modules, s'il sont manquant
function Module ($Module)
{
if (-Not (Get-Module -ListAvailable -Name $Module))
{
Install-Module $Module -Confirm:$false -Force
}
}
# Installation des modules dont on va avoir besoin
Module "PrtgAPI"
Module "PendingReboot"
# Fonction permettant de mettre en pause les sondes PRTG des serveurs aux heures prévues
function PRTGSched ($Srv, $h, $m, $PRTGopt)
{
$ReturnPRTGLog = $null
$PRTGParams = $null
$PRTGId = $null
# Identifiant de connexion PRTG
$PRTGLogin = "USERPRTG"
$PRTGHash = "HASHPASSWORD"
$PRTGServeur = "https://URLSUPERVISION.LAN"
# Connexion au serveur PRTG
Connect-PrtgServer -Server $PRTGServeur (New-Credential $PRTGLogin $PRTGHash) -PassHash
#Recupération de l'ID de la machine sur PRTG
$PRTGId = Get-Device $Srv
if ($PRTGId -ne $null)
{
# Suivant la valeur de $PRTGopt, on alimente les variables avec ce que l'on a besoin
switch ( $PRTGopt )
{
# Cette partie crée la planification, pour les serveurs
Schedule
{
$PRTGStart = (get-date -Hour $h -Minute $m -Second 0)
$PRTGEnd = $PRTGStart.AddMinutes(5)
$PRTGEnd = $PRTGEnd.ToString("yyyy-MM-dd-HH-mm-ss")
$PRTGStart = $PRTGStart.ToString("yyyy-MM-dd-HH-mm-ss")
#api https://www.paessler.com/manuals/prtg/application_programming_interface_api_definition
$PRTGParams = @{
"scheduledependency" = 0
"maintenable_" = 1
"maintstart_" = $PRTGStart
"maintend_" = $PRTGEnd
}
}
}
# l'appel est faite à PRTG avec les éléments dont il a besoin
Get-Device -Id $PRTGId.id | Set-ObjectProperty -RawParameters $PRTGParams -Force
# Je me déconnecte de PRTG
Disconnect-PrtgServer
}
else {
$ReturnPRTGLog = "True"
# Je me déconnecte de PRTG
Disconnect-PrtgServer
return $ReturnPRTGLog
}
}
#On recupère la liste des serveurs que l'on va exclure des tâches à effectuer (une ligne par serveur dans le fichier)
$ExcludeSrv = Get-Content ".\RestartSRVTachePlannifierPRTG-ListExcludeSrv.txt"
if ($readstart -eq "ou")
{
# j'utilise la fonction commune aux deux scripts (déclarées en debut de script)
$ServeurListe = OuCharger $listConSrv $ExcludeSrv
}
# On défini les variables de temps et du nom de la tâche qui sera crée
$Minute=55
#heure et hour sont crée car les serveurs sont en horaires anglaise alors que PRTG en francais
$Hour=7
$Heure=19
$GardeFou=0
$NameTask = "RebootSRV001"
$ListSRV = ""
$ListSRVError = ""
$ListSRVNotReboot = ""
# Gestion serveur par serveur
foreach ($serv in $ServeurListe)
{
if (Test-Connection -ComputerName $serv.Name -Quiet)
{
# On verifie si le serveur est en attente de redémarrage est on met les warning dans la variable $WarningPending
switch ((Test-PendingReboot -ComputerName $serv.Name -SkipConfigurationManagerClientCheck -WarningVariable WarningPending).IsRebootPending)
{
True
{
if ($debug -eq 1)
{
Write-Host "--------------------------------------------------------------------------------------------"
Write-Host "Vous etes dans le switch True (en attente de redémarrage)"
Write-Host "Nom du serveur : " $serv.Name
Write-Host "debug : " $debug
Write-Host "warning : " $WarningPending
Write-Host "Erreur : " $Error[0].Exception.message
Write-Host "--------------------------------------------------------------------------------------------"
}
# On verifie si le garde-fou est activé. Le garde-fou sert à éviter de dépasser la plage de redémarrage 20h > 23h30
if ($GardeFou -ne 1)
{
#On reinitialise la variable $Error
$Error.Clear()
# On verifie si la tache plannifier existe
$ReturnTask = Invoke-Command -ComputerName $serv.Name -ScriptBlock {Get-ScheduledTask | where-object {$_.TaskName -like $Using:NameTask}}
#si $ReturnTask retourne une erreur alors on quitte la boucle et on met le serveur en erreur en indiquant pourquoi
if ($Error.count -ne 0)
{
$ListSRVError += "Serveur : " + $serv.Name + "`n"
$ListSRVError += "`n-------------------------- Voici le message d'erreur ---------------------------------------`n"
$ListSRVError += $Error[0].Exception.message
$ListSRVError += "`n-------------------------- Fin du message d'erreur -----------------------------------------`n`n"
Continue
}
# le serveur doit être restart, j'implémente le nombre de minute et converti en heure si besoin
$Minute += 5
if (($Minute -eq 30) -and ($Hour -eq 11))
{
$GardeFou=1
$ListSRV += "############### RESTANT A RESTART PLUS TARD (HORS DELAI)`n"
}
if ($Minute -eq 60)
{
$Minute = 0
$Hour += 1
$Heure += 1
}
# Si la variable n'est pas null
if ($ReturnTask -ne $null)
{
# Alors on supprime la tâche, $using sert à utiliser des variables qui sont en local (dans le script)
Invoke-Command -ComputerName $serv.Name -ScriptBlock {Unregister-ScheduledTask $Using:NameTask -Confirm:$false}
# Lancement de la fonction avec l'heure défini actuellement
Task $serv.Name $Hour":"$Minute
# La sonde PRTG est mise en pause à l'heure prévu
$ReturnPRTGLog = PRTGSched $serv.Name $Heure $Minute "Schedule"
}
else
{
# Si aucune tâche n'est présente alors on lance la fonction avec l'heure défini actuellement
Task $serv.Name $Hour":"$Minute
# Je met la sonde PRTG en pause à l'heure prévu
$ReturnPRTGLog = PRTGSched $serv.Name $Heure $Minute "Schedule"
}
if ($ReturnPRTGLog -ne $null)
{
# Incrémentation de la liste des serveurs ayant besoin d'être redémarré
$ListSRV += $serv.Name + " restart à " + $Heure + ":" + $Minute + "`n"
}
else
{
$ListSRV += $serv.Name + " restart à " + $Heure + ":" + $Minute + " Pas de sonde PRTG trouvé, Suspension de la sonde non definie `n"
}
}
else
{
# Si le garde-fou est activé, alors on note les serveurs en attente de redémarrage. On ne plannifie pas de tâche car on n'a plus de temps disponible
$ListSRV += $serv.Name + " restart à " + $Heure + ":" + $Minute + "`n"
}
}
False
{
# On liste les serveurs qui n'ont pas besoin d'être redémarrer
$ListSRVNotReboot += $serv.Name + "`n"
if ($debug -eq 1)
{
Write-Host "--------------------------------------------------------------------------------------------"
Write-Host "Vous etes dans le switch False (Pas besoin de restart)"
Write-Host "Nom du serveur : " $serv.Name
Write-Host "debug : " $debug
Write-Host "warning : " $WarningPending
Write-Host "--------------------------------------------------------------------------------------------"
}
}
default
{
#Si le warning du switch Test-PendingReboot est egal a l'erreur RPC je l'indique
if (Select-String -InputObject $WarningPending -Pattern '0x800706BA' -Quiet)
{
$ListSRVError += "Serveur : " + $serv.Name + "`n"
$ListSRVError += "`n-------------------------- Voici le message d'erreur ---------------------------------------`n"
$ListSRVError += "N'arrive pas à se connecter à la machine (RPC) `n"
$ListSRVError += "`n-------------------------- Fin du message d'erreur -----------------------------------------`n`n"
}
else
{
# On note toutes les autres erreurs et indique les serveurs comme étant en erreurs
$ListSRVError += "Serveur : " + $serv.Name + "`n"
$ListSRVError += "`n-------------------------- Voici le message d'erreur ---------------------------------------`n"
$ListSRVError += "$WarningPending `n"
$ListSRVError += "`n-------------------------- Fin du message d'erreur -----------------------------------------`n`n"
}
#Sert de test pour savoir ou resort le warning
if ($debug -eq 1)
{
Write-Host "--------------------------------------------------------------------------------------------"
Write-Host "Vous etes dans le switch default (autre cas que redémarrage ou pas de redémarrage)"
Write-Host "Nom du serveur : " $serv.Name
Write-Host "debug : " $debug
Write-Host "warning : " $WarningPending
Write-Host "error : " $Error[0].FullyQualifiedErrorId
Write-Host "--------------------------------------------------------------------------------------------"
}
}
}
}
else
{
$ListSRVError += "Serveur : " + $serv.Name + "`n"
$ListSRVError += "`n-------------------------- Voici le message d'erreur ---------------------------------------`n"
$ListSRVError += "N'arrive pas à se connecter à la machine (PING) `n"
$ListSRVError += "`n-------------------------- Fin du message d'erreur -----------------------------------------`n`n"
}
}
# Si l'une des listes n'est pas vide, elle est convertit en caractère. On envoi le mail
if (($ListSRV -ne "") -or ($ListSRVError -ne "") -or ($ListSRVNotReboot -ne "")) {
$ListSRV | out-string
$ListSRVError | out-string
$ListSRVNotReboot | out-string
if ($debug -eq 1)
{
Write-Host "------------------------------------------- Serveurs qui n'ont pas besoin de redémarrage `n $ListSRVNotReboot `n ------------------------------------------- Serveurs en erreurs `n $ListSRVError `n ------------------------------------------- Serveurs qui vont redémarrer ce soir `n $ListSRV "
}
else
{
#Encodage UTF8
$encodingMail = [System.Text.Encoding]::UTF8
Send-MailMessage -From "EMAILEXPEDITEUR@TONDOM.FR" -To "DESTINATAIRE1@TONDOM.FR", "DESTINATAIRE2@TONDOM.FR" -Subject "Rapport des serveurs à restart" -SmtpServer "SERVEURSMTPRELAI" -Body "------------------------------------------- Serveurs qui n'ont pas besoin de redémarrage `n $ListSRVNotReboot `n ------------------------------------------- Serveurs en erreurs `n $ListSRVError `n ------------------------------------------- Serveurs qui vont redémarrer ce soir `n $ListSRV " -Encoding $encodingMail
}
}
Script Commun .\OuCharger.ps1
Modifier les chemins des OUs de vos serveurs en fonction de votre AD (option -SearchBase)
#Fonction commune à plusieurs scripts
function OuCharger ($listOUSrv, $ExcludeSrvList)
{
foreach ( $i in $listOUSrv )
{
switch ( $i )
{
'INTE'
{
$ServeurListe += @(Get-ADObject -LDAPFilter "(objectClass=Computer)" -SearchBase 'OU=INTE,OU=Serveur,DC=TONDOM,DC=lan' | Where-Object {$_.Name -notin $ExcludeSrvList} | Select-Object Name)
}
'PREPROD'
{
$ServeurListe += @(Get-ADObject -LDAPFilter "(objectClass=Computer)" -SearchBase 'OU=PREPROD,OU=Serveur,DC=TONDOM,DC=lan' | Where-Object {$_.Name -notin $ExcludeSrvList} | Select-Object Name)
}
'PROD'
{
$ServeurListe += @(Get-ADObject -LDAPFilter "(objectClass=Computer)" -SearchBase 'OU=PROD,OU=Serveur,DC=TONDOM,DC=lan' | Where-Object {$_.Name -notin $ExcludeSrvList} | Select-Object Name)
}
'TESTING'
{
$ServeurListe += @(Get-ADObject -LDAPFilter "(objectClass=Computer)" -SearchBase 'OU=TESTING,OU=Serveur,DC=TONDOM,DC=lan' | Where-Object {$_.Name -notin $ExcludeSrvList} | Select-Object Name)
}
default
{
Write-Information 'Veuillez remplir la variable$listOUSrv correctement'
Exit
}
}
}
return $ServeurListe
}
Attention faite des test en INTEGRATION avant, ne faite pas vos test directement en PROD