Windows PowerShellRestructuration du pipeline

Don Jones

On a beaucoup dit à quel point Windows PowerShell est différent, nouveau et passionnant, bien qu’il soit basé sur les concepts d’interface de ligne de commande qui existent depuis des décennies, principalement sur les systèmes d’exploitation basés sur UNIX et Linux. Mais la terminologie que Windows PowerShell partage avec ses prédécesseurs fait facilement

ignorer la véritable flexibilité et le caractère unique de Windows PowerShell™, ainsi qu’à quel point il est idéal pour l’environnement Windows®.

L’une des fonctionnalités les plus discutées de Windows PowerShell est son pipeline, mais il s’agit également, malheureusement, de l’une de ses fonctionnalités les plus mal comprises. Ceci s’explique par le fait qu’elle repose sur une terminologie qui a été définie au début des années 1970 et qui représentait autrefois une fonctionnalité très différente et beaucoup moins puissante.

L’origine des canaux

L’un des premiers shells UNIX créés était le shell Thompson, très primitif et comportant uniquement les éléments de langage de script les plus simples, sans aucune variable. Le noyau possédait une conception délibérément modeste car son seul but véritable était d’exécuter des programmes. Il a cependant introduit un concept essentiel amélioré par rapport aux autres shells de l’époque : les canaux. En utilisant les symboles < et >, il était possible d’indiquer au shell de rediriger entrée et sortie en provenance et à destination de commandes différentes. Un utilisateur était alors capable, par exemple, de rediriger la sortie d’une commande vers un fichier.

Cette syntaxe a plus tard évolué afin que la sortie d’une commande puisse également être redirigée vers l’entrée d’une autre commande, permettant à de longues séquences de commandes d’être mises bout à bout afin d’accomplir des tâches plus compliquées. Pour la version 4 du shell, le caractère de ligne verticale | a été adopté pour la redirection de canal et porte par conséquent depuis le nom de caractère « Pipe » (canal en anglais). Même les versions les plus anciennes de MS-DOS® utilisaient une redirection élémentaire par le bais de ce caractère, permettant par exemple à un utilisateur de rediriger la sortie de la commande type vers l’entrée d’une commande more pour créer un affichage page par page des fichiers texte longs.

Bien que le shell Thompson ait été largement considéré comme inadéquat à la date de la sortie d’UNIX version 6 en 1975, le concept de canaux était bien assimilé par les développeurs de shell et adapté dans plusieurs technologies utilisées de nos jours.

Redirection de texte

L’une des restrictions des shells est leur nature textuelle. Dans les systèmes d’exploitation basés sur UNIX, ce n’est en fait pas une restriction, mais plutôt le reflet du fonctionnement intrinsèque du système d’exploitation. Dans UNIX, presque toutes les ressources peuvent être représentées comme fichier d’un certain type, ce qui signifie que la possibilité de rediriger du texte d’une commande à une autre confère puissance et flexibilité importantes.

Le texte, toutefois, est définitivement restrictif lorsqu’il est question d’informations de gestion. Par exemple, si je vous présentais une liste des services s’exécutant sur un ordinateur Windows, vous pourriez certainement arriver à la déchiffrer. Je pourrais par exemple placer le nom du service dans la première colonne et son mode de démarrage dans la seconde. Votre cerveau humain puissant effectuerait de manière transparente et instantanée l’analyse, ou la traduction, de l’affichage de texte en informations pertinentes que vous pourriez utiliser. Les ordinateurs, cependant, sont loin d’être aussi intelligents : pour qu’un ordinateur puisse tirer quelque chose de significatif de cette liste, il serait peut-être nécessaire de lui indiquer que la première colonne se compose des caractères 1 à 20, que les caractères 22 à 40 forment la deuxième colonne, et ainsi de suite.

Pendant longtemps, ce type d’analyse de fichier texte était la seule méthode dont les administrateurs disposaient pour mettre bout à bout plusieurs commandes. En fait, les langages d’écriture de scripts tels que VBScript et Perl excellent dans la manipulation de chaînes, principalement parce qu’ils doivent pouvoir accepter la sortie texte d’un programme ou d’une commande et convertir ensuite cette sortie en données utiles pouvant être utilisées pour une tâche ultérieure. J’ai écrit des scripts VBScript, par exemple, qui utilisent la sortie de la commande Dir, extraient de la sortie les noms et dates de fichiers et déplacent ensuite les fichiers anciens et inutilisés vers un emplacement d’archive. Le traitement de chaîne est extrêmement difficile car des exceptions (les variations dans les données en entrée) surviennent presque toujours, vous obligeant à revoir la logique du script pour traiter toutes les permutations possibles.

En tant que forme d’écriture de script ou d’automatisation dans un environnement Windows, le traitement de chaîne est moins utile. En effet, Windows n’enregistre quant à lui que peu d’informations dans un format texte facile d’accès. Il utilise plutôt des magasins de données tels qu’Active Directory®, le Registre Windows et le magasin de certificats, pour que les utilisateurs de scripts utilisent d’abord un outil pour générer un certain type de sortie texte, puis un second pour effectuer son traitement et l’utiliser.

Les objets sont plus faciles

Les développeurs de logiciels Windows ont toujours eu la vie un peu plus facile. À l’origine, Microsoft a développé COM pour représenter spécifiquement les fonctionnements internes complexes de Windows d’une manière plus facile à utiliser. Aujourd’hui, Microsoft® .NET Framework poursuit cette tâche. Il représente les fonctionnements internes de logiciels de manière standardisée.

D’un point de vue générique, COM et .NET exposent les éléments en tant qu’objets (les développeurs de logiciels objecteront sans doute à cette simplification mais, dans l’intérêt de notre article, un terme simple suffira). Ces objets possèdent tous des membres de types variés. Dans notre cas, les propriétés et les méthodes des objets sont ce qui nous intéresse le plus. Une propriété décrit essentiellement un objet à certains égards ou modifie l’objet ou son comportement. Par exemple, un objet service peut disposer d’une propriété contenant le nom du service et d’une autre propriété contenant le mode de démarrage du service. Les méthodes font en sorte qu’un objet effectue une certaine action. Un objet service peut disposer de méthodes nommées Stop, Start, Pause et Resume représentant par exemple les diverses actions pouvant être exécutées avec le service.

Du point de vue de la programmation (ou de la génération de scripts), il est fait référence aux membres de l’objet avec une notation par points. Les objets sont souvent affectés à des variables, vous donnant ainsi une méthode de manipulation physique de l’objet. Si je dispose par exemple d’un service affecté à la variable $service, je peux arrêter ce service en utilisant la syntaxe $service.Stop. Je peux également récupérer le nom du service en affichant $service.Name.

Objets dans les canaux

Windows étant un système d’exploitation complexe et de taille importante, qui n’enregistre pas ses données de gestion dans des représentations de style texte, les anciennes techniques de shell ne sont pas vraiment adaptées à ce dernier. Supposons par exemple que je dispose d’un outil de ligne de commande nommé SvcList.exe produisant une liste mise en forme de services et leurs modes de démarrage. Dans le shell de ligne de commande de Windows (un shell dont les racines sont le shell MS-DOS, vieux de plusieurs décennies), je pourrais exécuter quelque chose de la forme :

SvcList.exe | MyScript.vbs 

Cette instruction récupère une liste de services et la redirige vers un fichier VBScript. Il faudrait que j’écrive un fichier VBScript pour traiter la liste mise en forme et exécuter toute action de mon choix, par exemple extraire tous les services dont le mode de démarrage est Disabled (Désactivé). Cette tâche prendrait du temps. En fin de compte, le problème est que SvcList.exe possède une sortie unique. Il ne partage par de format commun que les autres commandes peuvent facilement utiliser pour tirer parti de sa sortie.

Les objets, cependant, peuvent fournir ce format commun et c’est pourquoi le pipeline Windows PowerShell fonctionne avec les objets entiers et non uniquement le texte. Lorsque vous exécutez une cmdlet telle que Get-WMIObject, vous produisez un groupe (ou une collection en jargon de programmation) d’objets. Chaque objet est complet, avec des propriétés et méthodes vous permettant de le manipuler. Si je redirige les objets vers la cmdlet Where-Object, je peux les filtrer pour que seuls les objets de mon choix soient affichés. Where-Object n’a pas besoin d’analyser du texte parce qu’elle ne reçoit pas de texte : elle reçoit des objets. Par exemple :

Get-WMIObject Win32_Service | Where-Object {$_.StartMode -eq “Disabled” }

Ou, si vous préférez la syntaxe plus courte disponible au travers d’alias :

gwmi Win32_Service | where {$_.StartMode -eq “Disabled” }

Ce qui est intéressant est que Windows PowerShell passe toujours les objets dans le pipeline. Ce n’est qu’à la fin du pipeline (lorsqu’il n’existe plus rien vers lequel les objets peuvent être passés), que le shell génère une représentation textuelle des objets à l’aide de leurs règles de mise en forme intégrées. Examinons par exemple ceci :

Gwmi Win32_Service | where {$_.StartName –eq “LocalSystem” } | select Name,StartMode

Cet ensemble de trois cmdlets récupère tous les services de mon ordinateur local, filtre tous ceux qui n’utilisent pas le compte LocalSystem pour ouvrir une session et passe ensuite le reste à la cmdlet Select-Object, qui extrait uniquement deux propriétés, Name et StartMode, que je lui ai demandé de sélectionner. Le résultat est un rapport simple de services ouvrant une session en tant que LocalSystem (par exemple dans un but d’audit de sécurité).

Puisque toutes les cmdlets partagent un format de données commun (les objets) elles sont capables de partager des données entre elles sans traitement de chaîne compliqué. Et puisque Windows PowerShell possède de manière native la possibilité de créer une représentation sous forme de texte d’un objet, la fin de ce canal est assurément une sortie que je peux, en tant que personne, comprendre. La figure 1 illustre un exemple de sortie produite.

Figure 1 Sortie texte produite par un ensemble de cmdlets redirigées passant des objets.

Figure 1** Sortie texte produite par un ensemble de cmdlets redirigées passant des objets. **

Des canaux passionnants

La raison pour laquelle l’utilisation de canaux dans Windows PowerShell est si épatante est que tout dans Windows PowerShell est un objet, avec des propriétés et des méthodes que vous pouvez utiliser. Même un fichier texte est, du point de vue technique, une collection d’objets chaînes, chaque ligne de fichier faisant office d’objet chaîne unique et indépendant. Créez par exemple un fichier texte (à l’aide du Bloc-notes) nommé C:\Computers.txt. Remplissez le fichier avec du texte et exécutez ceci dans Windows PowerShell :

Get-Content C:\Computers.txt | Select-Object Length | Format-List

Ou, encore, si vous préférez moins de frappe, vous pouvez utiliser des alias :

gc C:\Computers.txt | select Length | fl

Ce code fournit une liste indiquant la longueur de chaque ligne de votre fichier texte en nombre de caractères. Get-Content récupère les objets chaînes du fichier, Select-Object extrait la propriété Length de chacun de ces objets et Format-List crée ensuite une sortie agréable et lisible pour vous. Bien que ceci ne soit peut-être pas un outil d’administration pratique à utiliser, il illustre que même une chose aussi simple qu’une ligne de texte est un objet dans Windows PowerShell.

La possibilité de rediriger des objets de cmdlet en cmdlet (ou même d’une cmdlet vers un script) permet la création d’instructions d’une ligne d’une puissance incroyable. Ce sont de simples chaînes de cmdlets attachées dans un long pipeline qui affinent une série d’objets pour vous donner exactement ce que vous voulez. Avec pratiquement aucune écriture de script ou de programme de quelque sorte que ce soit, les cmdlets de Windows PowerShell, chaînées ensemble dans un pipeline approprié, peuvent accomplir des résultats remarquables.

Prise en charge des générations futures

Le fait que les futurs produits serveurs de Microsoft s’appuient également sur Windows PowerShell permet d’étendre cette fonctionnalité. Au cours de la mise en œuvre d’un nouvel ordinateur Exchange Server 2007, vous pouvez par exemple utiliser Windows PowerShell pour récupérer toutes les boîtes aux lettres, filtrer tout celles qui ne correspondent pas au bureau dans lequel le nouveau serveur de messagerie sera situé et transférer ensuite ces boîtes aux lettres vers le nouveau serveur, tout ceci en une seule ligne de texte sans écriture de script. L’équipe Exchange Server 2007 a publié une longue liste d’instructions puissantes d’une seule ligne. Celles-ci démontrent avec efficacité la puissance du pipeline et les tâches administratives qu’il est capable d’accomplir.

L’astuce avec Windows PowerShell est de comprendre que, bien qu’il s’appuie sur des principes et des philosophies du monde d’UNIX établis depuis longtemps, ce nouvel outil est tout particulièrement adapté à l’administration de Windows. Ne laissez pas la banalité de la terminologie vous faire croire que Windows PowerShell est tout juste une imitation pour Windows du shell d’UNIX. Windows PowerShell contient de tous nouveaux concepts qui tirent parti de la plate-forme Windows et il est solidement associé à la manière de faire les choses dans Windows.

Don Jones est MVP Windows PowerShell et auteur de Windows PowerShell 101 (ScriptingTraining.com). Vous pouvez contacter Don sur le site www.ScriptingAnswers.com.

© 2008 Microsoft Corporation et CMP Media, LLC. Tous droits réservés. Toute reproduction, totale ou partielle, est interdite sans autorisation préalable.