PowerShell pour les administrateurs système

imageBonjour, Habitants! PowerShell est à la fois un langage de script et un shell de commande qui vous permet de gérer et d'automatiser presque toutes les tâches. Dans PowerShell pour les administrateurs système, le propriétaire de Microsoft MVP, Adam Bertram, alias «l'automate», vous montre comment utiliser PowerShell pour que le lecteur ait enfin le temps pour les jouets, le yoga et les chats. Vous apprendrez à: -Combiner des commandes, contrôler le flux d'exécution, gérer les erreurs, écrire des scripts, les exécuter à distance et les tester à l'aide du framework de test Pester. -Analyser des données structurées telles que XML et JSON, travailler avec des services populaires (tels que Active Directory, Azure et Amazon Web Services), créer des systèmes de surveillance de serveur. -Créer et concevoir des modules PowerShell. -Utilisez PowerShell pour plus de commodité,installation Windows entièrement automatisée. -Créez une forêt Active Directory avec juste un hôte Hyper-V et quelques fichiers ISO. -Créez d'innombrables serveurs Web et SQL avec seulement quelques lignes de code! Des exemples de la vie réelle aident à combler le fossé entre la théorie et le travail dans un système réel, et l'humour léger de l'auteur facilite la lecture. Arrêtez de vous fier à des logiciels coûteux et à de vagues conseils du Web!



Pour qui est ce livre
- , . DevOps, , / (CI/CD).



, PowerShell . PowerShell « Windows» — Microsoft, PowerShell . , , .



Contrôle du flux



Répétons un peu. Au chapitre 3, nous avons appris comment combiner des commandes à l'aide d'un pipeline et de scripts externes. Le chapitre 2 a couvert les variables et comment les utiliser pour stocker des valeurs. L'un des principaux avantages du travail avec des variables est la possibilité de les utiliser pour écrire du code qui ne fonctionne pas avec la valeur, mais avec le «sens». Au lieu de travailler avec le nombre 3, par exemple, vous travaillerez avec le concept général de $ serverCount. Cela vous permet d'écrire du code qui fonctionne de la même manière que vous ayez un, deux ou mille serveurs. Combinez cette capacité avec la possibilité d'enregistrer votre code dans des scripts qui peuvent être exécutés sur différents ordinateurs, et vous pouvez commencer à résoudre des problèmes à une échelle beaucoup plus grande.



Cependant, dans la vie, il est parfois important que vous travailliez avec un serveur, avec deux ou avec mille. Jusqu'à présent, vous ne disposez pas d'un moyen approprié pour en tenir compte, et vos scripts s'exécutent simplement de haut en bas, incapables de s'adapter en fonction de certaines valeurs. Dans ce chapitre, nous utiliserons le flux de contrôle et la logique conditionnelle pour écrire des scripts qui exécuteront différentes commandes en fonction des valeurs sur lesquelles elles opèrent. À la fin du chapitre, vous apprendrez à utiliser les instructions if / then et switch, ainsi que diverses boucles, pour donner à votre code la flexibilité indispensable.



Un peu sur le flux de contrôle



Nous allons écrire un script qui lit le contenu d'un fichier stocké sur plusieurs ordinateurs distants. Pour continuer, téléchargez un fichier appelé App_configuration.txt à partir des documents du livre sur github.com/adbertram/PowerShellForSysadmins/ et placez-le à la racine du lecteur C: \ sur plusieurs ordinateurs distants. Si vous n'avez pas d'ordinateurs distants, continuez à lire pour le moment. Pour cet exemple, j'utiliserai les serveurs nommés SRV1, SRV2, SRV3, SRV4 et SRV5.



Pour accéder au contenu du fichier, utilisez la commande Get-Content et spécifiez le chemin d'accès au fichier dans la valeur de l'argument de paramètre Path, comme indiqué ci-dessous:



Get-Content -Path "\\ servername \ c $ \ App_configuration.txt "



Tout d'abord, sauvegardons tous les noms de nos serveurs dans un tableau et exécutons cette commande pour chaque serveur. Ouvrez un nouveau fichier .ps1 et entrez le code du Listing 4.1 dedans.



Liste 4.1. Extraction du contenu des fichiers à partir de plusieurs serveurs



$servers = @('SRV1','SRV2','SRV3','SRV4','SRV5')
Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[1])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[2])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[3])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[4])\c$\App_configuration.txt"
      
      





En théorie, ce code devrait fonctionner sans problème. Mais cet exemple suppose que quelque chose ne va pas pour vous. Que faire si le serveur SRV2 est en panne? Que faire si quelqu'un oublie de mettre App_configuration.txt sur SRV4? Ou peut-être que quelqu'un a changé le chemin du fichier? Vous pouvez écrire un script distinct pour chaque serveur, mais cette solution ne sera pas mise à l'échelle, d'autant plus que vous commencez à ajouter de plus en plus de serveurs. Vous avez besoin d'un code qui fonctionne selon la situation.



L'idée derrière le flux de contrôle est qu'il vous permet d'exécuter différents ensembles d'instructions basés sur une logique prédéfinie. Imaginez que vos scripts soient exécutés selon un chemin spécifique. Jusqu'à présent, votre chemin est simple - de la première ligne de code à la dernière. Cependant, vous pouvez ajouter des fourches en cours de route, revenir aux endroits que vous avez déjà visités ou sauter par-dessus. En forçant les chemins d'exécution de votre script, vous lui donnez plus de flexibilité, vous permettant de gérer de nombreuses situations avec un seul script.



Nous allons commencer par examiner le type le plus simple de flux de contrôle, l'instruction conditionnelle.



Utilisation d'instructions conditionnelles



Au chapitre 2, nous avons appris qu'il existe des valeurs logiques: vrai et faux. Les booléens vous permettent de créer des instructions conditionnelles qui indiquent à PowerShell d'exécuter un bloc de code spécifique selon qu'une expression (appelée condition) est évaluée à True ou False. Une condition est une question oui / non. Avez-vous plus de cinq serveurs? Le serveur 3 est-il en cours d'exécution? Le chemin du fichier existe-t-il? Pour commencer à utiliser des instructions conditionnelles, voyons comment convertir ces questions en expressions.



Création d'expressions avec des opérateurs Vous



pouvez écrire des expressions logiques à l'aide d'opérateurs de comparaison qui comparent des valeurs. Pour utiliser un opérateur de comparaison, vous devez le placer entre deux valeurs, par exemple:



PS> 1 –eq 1
True
      
      





Dans ce cas, l'opérateur –eq vous permet de déterminer l'équivalence de deux valeurs.

Vous trouverez ci-dessous une liste des opérateurs de comparaison les plus courants que nous utiliserons:



-eq compare deux valeurs et renvoie True si elles sont égales.



-ne compare deux valeurs et renvoie True si elles ne sont pas égales.



-gt compare deux valeurs et renvoie True si la première est supérieure à la seconde.



-ge compare deux valeurs et renvoie True si la première est supérieure ou égale à la seconde.



-lt compare deux valeurs et renvoie True si la première est inférieure à la seconde.



-le compare deux valeurs et renvoie True si la première est inférieure ou égale à la seconde.



-contains renvoie True si la deuxième valeur fait partie de la première. Par exemple, cet opérateur vous permet de déterminer si une valeur est à l'intérieur d'un tableau.



PowerShell dispose également d'opérateurs de comparaison plus avancés. Nous ne nous attarderons pas sur eux ici, mais je vous recommande de les lire dans la documentation Microsoft à docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators ou dans la section Aide de PowerShell (voir chapitre 1).



Vous pouvez utiliser les opérateurs ci-dessus pour comparer des variables et des valeurs. Mais l'expression n'a pas à être une comparaison. Parfois, les commandes PowerShell peuvent être utilisées comme conditions. Dans l'exemple précédent, nous voulions connaître la disponibilité du serveur. Vous pouvez utiliser l'applet de commande Test-Connection pour tester la connexion au serveur. En règle générale, la sortie de l'applet de commande Test-Connection contient de nombreuses informations différentes, mais avec le paramètre Quiet, vous pouvez forcer la commande à renvoyer True ou False, et le paramètre Count peut limiter le test à une tentative.



PS> Test-Connection -ComputerName offlineserver -Quiet -Count 1
False
      
      





PS> Test-Connection -ComputerName onlineserver -Quiet -Count 1
True
      
      





Pour savoir si le serveur est en panne, vous pouvez utiliser l'opérateur –not pour inverser l'expression:



PS> -not (Test-Connection -ComputerName offlineserver -Quiet -Count 1)
True
      
      





Maintenant que vous êtes familiarisé avec les expressions de base, examinons l'opérateur conditionnel le plus simple.



L'instruction if L'instruction



if fonctionne simplement: si X est vrai, alors faites Y. C'est tout!



Pour utiliser une instruction dans une expression, écrivez le mot clé if suivi de parenthèses contenant la condition. L'expression est suivie d'un bloc de code entre accolades. PowerShell n'exécutera ce bloc de code que si l'expression a la valeur True. Si l'expression if est évaluée à False ou ne renvoie rien du tout, le bloc de code ne sera pas exécuté. La syntaxe de l'instruction if / then est présentée dans l'extrait 4.2.



Liste 4.2. Si la syntaxe de l'instruction



if () {
   #  ,   
}
      
      





Cet exemple a un peu de nouvelle syntaxe: le caractère dièse (#) indique un commentaire - c'est du texte que PowerShell ignore. Vous pouvez utiliser les commentaires pour laisser des notes et des descriptions utiles pour vous-même ou pour quelqu'un d'autre qui lira plus tard votre code.



Maintenant, jetons un autre regard sur le code montré dans l'extrait 4.1. Je vais vous montrer comment utiliser une instruction if pour éviter d'essayer d'atteindre un serveur mort. Nous avons déjà vu dans la section précédente que la commande Test-Connection peut être utilisée comme une expression qui renvoie True ou False, donc pour l'instant enveloppons Test-Connection dans une instruction if, puis utilisons la commande Get-Content pour éviter d'essayer d'accéder un serveur mort. ... Pour l'instant, nous ne changerons que le code du premier serveur, comme indiqué dans l'extrait 4.3.



Liste 4.3. Utilisation d'une instruction if pour accéder sélectivement



$servers = @('SRV1','SRV2','SRV3','SRV4','SRV5')
if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
}
Get-Content -Path "\\$($servers[1])\c$\App_configuration.txt"
----
      
      





Puisque vous avez Get-Content dans votre instruction if, vous ne rencontrerez aucune erreur si vous essayez d'accéder à un serveur défectueux; si le test échoue, votre script sait qu'il ne doit pas essayer de lire le fichier. Le code essaiera d'accéder au serveur uniquement s'il sait déjà qu'il est activé. Mais notez que ce code ne se déclenche que si la condition est vraie. Très souvent, vous devrez spécifier un comportement de script pour une condition vraie et un autre pour une condition fausse. Dans la section suivante, vous verrez comment définir le comportement d'une condition fausse à l'aide de l'instruction else.



Sinon déclaration



Pour fournir à votre instruction if une alternative, vous pouvez utiliser le mot-clé else après la parenthèse fermante du bloc if, suivi d'une autre paire d'accolades contenant le bloc de code. Comme le montre le Listing 4.4, nous utiliserons une instruction else pour renvoyer une erreur à la console si le premier serveur ne répond pas.



Liste 4.4. Utilisation de la clause else pour exécuter du code si la condition n'est

pas vraie



if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
} else {
   Write-Error -Message "The server $($servers[0]) is not responding!"
}
      
      





L'instruction if / else fonctionne très bien lorsque vous avez deux situations qui s'excluent mutuellement. Dans ce cas, le serveur est connecté ou non, c'est-à-dire que nous n'avons besoin que de deux branches du code. Voyons comment gérer des situations plus complexes.



Déclaration Elseif



L'instruction else couvre la situation inverse: si cela ne fonctionne pas, faites-le quand même. Cette approche fonctionne pour les conditions binaires, c'est-à-dire lorsque le serveur est en cours d'exécution ou non. Mais parfois, vous devez faire face à un grand nombre d'options. Par exemple, supposons que vous ayez un serveur qui ne possède pas le fichier souhaité et que vous ayez stocké le nom de ce serveur dans la variable $ problemServer (ajoutez cette ligne de code à votre script!). Cela signifie que vous avez besoin d'une vérification supplémentaire pour voir si le serveur que vous interrogez actuellement est le serveur problématique. Cela peut être accompli avec des instructions if imbriquées, comme indiqué dans le code ci-dessous:



if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   if ($servers[0] –eq $problemServer) {
      Write-Error -Message "The server $servers[0] does not have the right
         file!"
   } else {
      Get-Content -Path "\\$servers[0]\c$\App_configuration.txt"
   }
} else {
   Write-Error -Message "The server $servers[0] is not responding!"
}
----
      
      





Mais il existe un moyen plus simple d'implémenter la même logique, avec une instruction elseif, qui vous permet de vérifier une condition supplémentaire avant de revenir au bloc else. La syntaxe du bloc elseif est identique à la syntaxe du bloc if. Donc, pour tester le serveur problématique avec l'instruction elseif, exécutez le code du Listing 4.5.



Liste 4.5. Utilisation du bloc elseif



if (-not (Test-Connection -ComputerName $servers[0] -Quiet -Count 1)) { 
   Write-Error -Message "The server $servers[0] is not responding!"
} elseif ($servers[0] –eq $problemServer) 
   Write-Error -Message "The server $servers[0] does not have the right file!"
} else {
   Get-Content -Path "\\$servers[0]\c$\App_configuration.txt"
}
----
      
      





Veuillez noter que nous n'avons pas simplement ajouté une instruction elseif, mais en même temps changé la logique du code. Nous pouvons maintenant vérifier si le serveur est hors ligne à l'aide de l'opérateur –not. Ensuite, une fois que nous avons déterminé l'état du réseau du serveur, nous vérifions si cela pose problème. Sinon, nous utilisons l'instruction else pour déclencher le comportement d'extraction de fichier par défaut. Comme vous pouvez le voir, il existe plusieurs façons de structurer votre code de cette manière. L'important est que le code fonctionne et qu'il soit lisible par une personne de l'extérieur, que ce soit votre collègue le voyant pour la première fois, ou vous-même quelque temps après l'avoir écrit.



Vous pouvez enchaîner autant d'instructions elseif que vous le souhaitez pour s'adapter à une grande variété de circonstances. Cependant, les instructions elseif sont mutuellement exclusives: lorsque l'un des elseifs est évalué à True, PowerShell exécute uniquement son code et ne vérifie pas les autres cas. Dans le Listing 4.5, cela n'a posé aucun problème, puisque vous n'aviez besoin de tester le serveur que pour des "problèmes" après avoir vérifié la santé, mais à l'avenir, je vous conseille de garder cette fonctionnalité à l'esprit.



Les instructions if, else et elseif sont idéales pour implémenter des réponses de code à de simples questions oui / non. Dans la section suivante, vous apprendrez à travailler avec une logique plus complexe.



Instruction Switch



Modifions un peu notre exemple. Disons que nous avons cinq serveurs et que sur chaque serveur, le chemin d'accès au fichier requis est différent. Sur la base de ce que vous savez maintenant, vous devrez créer une instruction elseif distincte pour chaque serveur. Cela fonctionnera, mais il existe une méthode plus pratique.



Veuillez noter que nous allons maintenant travailler avec un autre type de condition. Si auparavant nous avions besoin de réponses à des questions telles que "oui / non", nous voulons maintenant comprendre le sens spécifique d'une chose. Est-ce un serveur SRV1? SRV2? Etc. Si vous ne travailliez qu'avec une ou deux valeurs spécifiques, une instruction if fonctionnerait, mais dans ce cas, une instruction switch fonctionne beaucoup mieux.



L'instruction switch vous permet d'exécuter différents morceaux de code en fonction d'une certaine valeur. Il se compose du mot-clé switch suivi d'une expression entre parenthèses. À l'intérieur du bloc de commutation se trouve une série d'instructions, structurées comme ceci: vous spécifiez d'abord la valeur, suivie d'un ensemble d'accolades contenant le bloc de code, et enfin le bloc par défaut, comme indiqué dans l'extrait 4.6.



Listing 4.6. Changer de modèle de déclaration



switch () {
    {
      # 
   }
    {
   }
   default {
     # ,     
   }
}
      
      





Une instruction switch peut contenir un nombre presque illimité de valeurs. Si l'expression est évaluée à une valeur, le code correspondant dans le bloc est exécuté. L'important est que, contrairement à elseif, après avoir exécuté un bloc de code, PowerShell continuera à vérifier le reste des conditions, sauf indication contraire. Si aucune des valeurs ne correspond, PowerShell exécutera le code dans le bloc par défaut. Pour arrêter l'itération sur des conditions dans une instruction switch, utilisez le mot-clé break à la fin du bloc de code, comme indiqué dans l'extrait 4.7.



Listing 4.7. Utilisation du mot clé break dans une instruction switch



switch () {
    {
      # 
      break
   }
----
      
      





Le mot-clé break vous permet de créer des conditions dans une instruction switch qui s'excluent mutuellement. Revenons à notre exemple avec cinq serveurs et le même fichier avec des chemins différents. Vous savez que le serveur avec lequel vous travaillez ne peut avoir qu'une seule valeur (c'est-à-dire qu'il ne peut pas être nommé à la fois SRV1 et SRV2 en même temps), vous devez donc utiliser des instructions break. Votre script doit ressembler à celui présenté dans l'extrait 4.8.



Liste 4.8. Vérification de divers serveurs avec une instruction switch



$currentServer = $servers[0]
switch ($currentServer) {
   $servers[0] {
      # Check if server is online and get content at SRV1 path.
      break
   }
   $servers[1] {
      ## Check if server is online and get content at SRV2 path.
      break
   }
   $servers[2] {
      ## Check if server is online and get content at SRV3 path.
      break
   }
----
      
      





Vous pouvez réécrire ce code en utilisant uniquement les instructions if et elseif (et je vous recommande vraiment d'essayer ceci!). Dans tous les cas, quelle que soit la méthode que vous choisissez, vous avez besoin de la même structure pour chaque serveur de la liste, ce qui signifie que votre scénario va être assez long - imaginez simplement tester cinq cents serveurs au lieu de cinq. Dans la section suivante, vous apprendrez à vous débarrasser de ce problème en utilisant l'une des structures de flux de contrôle les plus fondamentales - une boucle.



Utilisation de boucles



Il existe une bonne règle de base pour le travail sur ordinateur: ne vous répétez pas (DRY). Si vous vous retrouvez à faire le même travail, il y a de fortes chances qu'il existe un moyen de l'automatiser. C'est la même chose avec le codage: si vous utilisez les mêmes lignes encore et encore, il y a probablement une meilleure solution.



Une façon d'éviter les répétitions est d'utiliser des boucles. Une boucle vous permet d'exécuter du code à plusieurs reprises jusqu'à ce que certaines conditions spécifiées changent. La condition d'arrêt peut démarrer la boucle un nombre spécifié de fois, soit jusqu'à ce qu'une valeur booléenne change, soit définir la boucle pour qu'elle s'exécute indéfiniment. Nous appellerons chaque passage de la boucle une itération.



PowerShell propose cinq types de boucles: foreach, for, do / while, do / until et while. Dans cette section, nous discuterons de chaque type de boucle, mettrons en évidence leurs caractéristiques uniques et mettrons en évidence les meilleures situations pour les utiliser.



À propos de l'auteur



Adam Bertram est un expert chevronné des TI et des affaires Internet avec 20 ans d'expérience. Entrepreneur, influenceur informatique, MVP Microsoft, Blogger, Responsable de la formation et Auteur en marketing de contenu, travaillant avec de nombreuses sociétés informatiques. Adam a également fondé la populaire plateforme TechSnips pour développer les compétences des professionnels de l'informatique (techsnips.io).



Plus de détails sur le livre peuvent être trouvés sur le site de la maison d'édition

» Table des matières

» Extrait



Pour les Habitants, une remise de 25% sur le coupon - PowerShell



Lors du paiement de la version papier du livre, un e-book est envoyé à l'e-mail.



All Articles