Le blog technique

Toutes les astuces #tech des collaborateurs de PI Services.

#openblogPI

Retrouvez les articles à la une

Powershell: Gestion des erreurs sur Cmdlet

 

Dans mon précédent blog, je vous est montré comment on pouvait mettre en place la gestion d’erreur sur des commandes sous powershell qui ne sont pas des CMDLET, cette fois-ci nous allons voir comment appliquer la gestion d’erreur sur une CMDLET

PERIMETRE: Dans le cadre de l’amélioration des script powershell concernant la vérification des services après le redémarrage des serveurs en production chez un de nos client, celui-ci à laisser le soin au service architecture de trouver une solution.

 

Mon script d’origine:

######SERVEURS A REDEMARRER################

$Computerstring = "orches1"
$Computerdestination = $Computerstring.Split(",")

######SERVICES A ARRETER ET REDEMARRER################

$Servicesstring = "wudfsvc"
$Servicesname = $Servicesstring.Split(",")

######LOG CREER POUR LA VERIFICATION AVANT L’ARRET DES SERVICES SUR CHAQUES SERVEURS + GESTION ERREUR SUR SYNTAXE Command###
$StatusService = foreach ($vm in $Computerdestination){
         get-Service -ComputerName $vm -name $Servicesname | select status,name,machinename }
       

#GESTION ERREUR DES SERVICES

$ExitCodeService = foreach ($SRVservices in $StatusService) {
if ($($SRVservices.status) -eq "Running"){
"Success : Service(s) Running" + $SRVservices
}else{
"Error : Service(s)" + $SRVservices
}
}

$ErrorStatusSVC = if ($StatusService -eq $null){
"Error : Service(s) "
}else{
"Success : Service(s)"
}  

Voici le résultat pour les sortie erreurs:

$ExitCodeService

image

$ErrorStatusSVC

image

Vous voyez au dessus $ExitCodeService prend en compte que le service wudfsvc étant arrêté comme SUCCESS condition voulu ceci est normal et que $ErrorStatusSVC à été mise en place pour anticipé les erreurs $ExitCodeService si aucune valeur ne ressort ($ExitCodeService = VIDE) cela peut être une erreur de syntaxe, de service ou de serveurs inaccessible ou inexistant

Par contre aucune erreur détailler il faut effectuer une recherche supplémentaire.

 

Mon script amélioré:

######SERVEURS A REDEMARRER################

$Computerstring = "orches1"
$Computerdestination = $Computerstring.Split(",")

######SERVICES A ARRETER ET REDEMARRER################

$Servicesstring = "wudfsvc"
$Servicesname = $Servicesstring.Split(",")

######LOG CREER POUR LA VERIFICATION AVANT L’ARRET DES SERVICES SUR CHAQUES SERVEURS + GESTION ERREUR SUR SYNTAXE Command###

$StatusService =
Try {
foreach ($vm in $Computerdestination){
         get-Service -ComputerName $vm -name $Servicesname -ErrorAction stop | select status,name,machinename
        }
}catch{
   "$vm => " + $Error[0]
   }

#GESTION ERREUR DES SERVICES

$ExitCodeService =                                                                                         foreach ($SRVservices in $StatusService) {
            if ($($SRVservices.status) -eq "stopped"){
                    "Success:" + $SRVservices
            }else{
                   "Error:" + $SRVservices
            } 
    }

Voici le résultat pour la sortie d’erreur:

La correction se base sur la gestion d’erreur avec les commandes Try et Catch

Dans la partie Try  entre crochets, la commande get-service doit obligatoirement avoir l’option qui permet la sortie d’erreur qui se nomme        –ErrorAction stop cela permettra d’avoir dans la partie catch les messages d’erreur le déroulement du processus $Error[0] . 

Message des erreurs qui sont géré dans : $StatusService

image

Erreur sur le compte d’ordinateur inexistant ou inaccessible:

image

Erreur sur le service inexistant ou inaccessible:

image

Erreur sur la syntaxe commande get-service:

image

Les messages de sortie sont aussi retransmis dans la variable  $ExitCodeService à l’aide des conditions if et else

Powershell – Exemple de transfert de données vers un système Unix

 

A la suite de la récupération d’un dataset issu d’une requête a une base sql on veut exporter et transférer les données vers un système Unix.

Comme indiqué dans le code, a la suite de la validation du fait que le résultat de la requête contienne des données (RequestSQL OK),  on converti le dataset en csv vers un fichier local ($FullLocalFile):

($DataSet.Tables[0] | convertto-csv -Delimiter « ; » -NoTypeInformation)  | Out-File -FilePath $FullLocalFile

Puis on récupère le contenu du fichier pour ensuite le convertir au format UTF8 (au passage on écrase le fichier d’origine):

$content=get-content $FullLocalFile
Set-Content -value $content -Encoding UTF8 -Path $FullLocalFile –Force

Enfin on envoi en ftp le fichier vers le système Unix (en construisant dynamiquement le fichier de commande):

N.B: Il est possible que le mode de transfert (ascii ou binary) ait une influence sur le résultat du transfert. N’hésitez pas a tester les deux cas.

#construction fichier ftpcommands
New-Item -Path « $LocalDirectory\ftpcommands.txt » -ItemType file -Force -value `
« open monserverunix
user1
password
ascii
cd /monappli/data
lcd $LocalDirectory
mput $FileName
Y
bye »

#Envoi FTP et verification
ftp.exe -s:$LocalDirectory\ftpcommands.txt > « $LocalDirectory\resultatftp.txt »

(…)

#suppression du fichier ftpcommands
Remove-Item -Path « $LocalDirectory\ftpcommands.txt »
Remove-Item -Path « $LocalDirectory\resultatftp.txt »

 

$LocalDirectory=« D:\Data«  $FileName=« data.csv«  $FullLocalFile=« $LocalDirectory\$FileName«  (…) #Si le dataset est vide => Echec de la requête => $RequestSuccess=$false If (($DataSet.Tables[0] | MeasureObject).count -eq « 0« ) { $RequestSuccess=$false writehost ForegroundColor blue « Dataset vide – FIN DU SCRIPT«  Exit } Else { $RequestSuccess=$true writehost ForegroundColor green « RequestSQL OK«  #Export du fichier CSV en local ($DataSet.Tables[0] | converttocsv Delimiter « ;«  NoTypeInformation) | Out-File FilePath $FullLocalFile #Recuperation du contenu et conversion en UTF8 pour compatibilité Unix $content=getcontent $FullLocalFile SetContent value $content Encoding UTF8 Path $FullLocalFile Force } #construction fichier ftpcommands NewItem Path « $LocalDirectory\ftpcommands.txt«  ItemType file Force value ` « open monserverunix user1 password ascii cd /monappli/data lcd $LocalDirectory mput $FileName Y bye«  #Envoi FTP et verification ftp.exe s:$LocalDirectory\ftpcommands.txt > « $LocalDirectory\resultatftp.txt«  (…) #suppression du fichier ftpcommands RemoveItem Path « $LocalDirectory\ftpcommands.txt«  RemoveItem Path « $LocalDirectory\resultatftp.txt« 

Powershell – Script – Suppression création de compteur de performance

 

Il peut être nécessaire dans le cas d’un script insérant des données de performance de supprimer/recréer l’objet de performance

L’exemple ci-dessous montre la suppression ré-création d’un objet MyObject et d’un compteur de performance Mycounter1.

On vérifie l’existence de l’objet de performance via wmi et l’objet .net [Diagnostics.PerformanceCounterCategory]

On supprime MyObject

On recrée l’objet et son compteur  via Diagnostics.CounterCreationDataCollection et Diagnostics.CounterCreationData

On soumet la création de l’objet “global” via [Diagnostics.PerformanceCounterCategory]

Le compteur peut a partir de là être alimenté et interrogé.

 

if((GetWmiObject Query « Select * from Win32_perfformatteddata_MyObject_MyObject« ).MyCounter1 -eq 0 ` -OR (GetWmiObject Query « Select * from Win32_perfformatteddata_MyObject_MyObject« ).MyCounter1 -eq $null ` -AND [Diagnostics.PerformanceCounterCategory]::Exists(“MyObject”)) { writehost « Suppression et re-creation de l’objet de performance MyObject«  #Suppression [Diagnostics.PerformanceCounterCategory]::Delete(“MyObject”); #Creation de l’objet de perf $script:cntrColl = NewObject Diagnostics.CounterCreationDataCollection; WriteHost « Add counter 1« ; $counter = NewObject Diagnostics.CounterCreationData; $counter.CounterName = « Mycounter1« ; $counter.CounterHelp = « Help for Counter_1« ; $counter.CounterType = [Diagnostics.PerformanceCounterType]::NumberOfItems64; $script:cntrColl.Add($counter); #Ajout du compteur WriteHost « Ajout du compteur a PerfMon« ; [Diagnostics.PerformanceCounterCategory]::Create(“MyObject”, “My counter”, $script:cntrColl); }