Comment debugger un script qui utilise Popd sans tout casser ?

La commande Popd (alias de Pop-Location en PowerShell) retire le dernier répertoire empilé par Pushd et y repositionne la session. Le problème survient quand une erreur interrompt le script entre le Pushd et le Popd : la pile de répertoires se retrouve dans un état incohérent, et le reste de l’exécution travaille depuis un chemin inattendu.

Debugger ce type de script exige de comprendre la pile de localisation, de protéger l’appel à Popd contre les exceptions, puis de tracer l’état du répertoire à chaque étape critique.

A lire également : Rank by ping com vu par un développeur : regard technique et décalé

Pile de localisation PowerShell : ce que Pushd et Popd manipulent

Pushd (alias de Push-Location) empile le répertoire courant sur une pile LIFO, puis change le répertoire actif. Popd dépile et restaure. La pile n’est pas visible à l’écran par défaut, ce qui rend les bugs silencieux.

Quand un script enchaîne plusieurs Pushd sans le nombre exact de Popd correspondants, la pile reste polluée. Un deuxième appel du même script partira alors d’un répertoire résiduel laissé par l’exécution précédente. C’est la source la plus fréquente de « casse » involontaire : un Popd manquant décale toute la pile pour le reste de la session.

A découvrir également : Swiss file transfer et collaboration d'équipe : centraliser vos échanges de fichiers

Pour inspecter l’état de la pile à tout moment, la commande Get-Location -Stack affiche les entrées empilées. Placer cet appel en début et en fin de script donne une trace immédiate de toute fuite.

Programmeuse travaillant sur un débogage de script shell avec commandes popd et pushd dans un espace de coworking

Protéger Popd avec try/finally dans un script PowerShell

Le scénario fragile typique ressemble à ceci : le script fait un Pushd vers un dossier de travail, exécute des opérations, puis appelle Popd en dernière ligne. Si une exception survient entre les deux, Popd n’est jamais atteint.

La parade la plus fiable utilise un bloc try/finally. Le code placé dans finally s’exécute que le bloc try réussisse ou échoue. Le Popd y est garanti.

Structure minimale du bloc try/finally

Le squelette à adopter :

  • Pushd vers le répertoire cible avant le bloc try, pour que la pile soit alimentée avant toute opération risquée.
  • Placer l’ensemble des opérations métier dans le bloc try.
  • Placer Popd dans le bloc finally, jamais dans catch seul (un catch ne couvre que les erreurs interceptées, pas les terminaisons inattendues).
  • Ajouter dans le catch un Write-Error ou un Write-Warning pour ne pas perdre l’information sur l’exception.

Avec cette structure, même si le script plante, la session revient au répertoire d’origine. Le bloc finally est le seul endroit sûr pour un Popd.

Erreurs non terminantes et le piège de ErrorAction

PowerShell distingue les erreurs terminantes (qui déclenchent catch) des erreurs non terminantes (qui s’affichent mais laissent le script continuer). Par défaut, une commande comme Get-ChildItem sur un chemin inexistant ne déclenche pas catch.

Si le script dépend d’une opération qui peut échouer silencieusement, le répertoire courant reste celui du Pushd sans que rien ne signale le problème. Pour forcer la remontée dans le catch, ajouter -ErrorAction Stop aux commandes critiques ou définir $ErrorActionPreference = 'Stop' en tête de script. Sans cette précaution, le try/finally fonctionne mais le script produit des résultats erronés depuis le mauvais répertoire, sans lever d’alerte.

Tracer l’état du répertoire pendant le debug d’un script

Placer des points de contrôle dans le script permet de vérifier que le répertoire courant correspond à celui attendu à chaque étape. Deux techniques complémentaires couvrent la majorité des cas.

Write-Debug et la variable automatique $PWD

La commande Write-Debug n’affiche rien par défaut. Elle ne produit une sortie que lorsque le paramètre -Debug est passé au script ou que $DebugPreference vaut 'Continue'. Ce comportement la rend idéale pour des traces de répertoire permanentes dans le code, invisibles en production.

Insérer Write-Debug "Répertoire courant : $PWD" après chaque opération de fichier permet de reconstituer le chemin suivi par le script. La variable $PWD reflète toujours le répertoire actif, y compris après un Pushd ou Popd.

Combiner Get-Location -Stack avec Write-Verbose

Pour aller plus loin, tracer aussi la pile elle-même révèle les déséquilibres. Un appel Write-Verbose "Pile : $((Get-Location -Stack).Count) entrée(s)" placé avant et après chaque Pushd/Popd met en évidence toute fuite. Si le compteur ne revient pas à sa valeur initiale en fin de script, un empilement ou un dépilement est manquant.

Deux développeurs collaborant pour déboguer un script bash contenant des erreurs liées aux commandes de gestion de pile de répertoires

Debugger Popd en contexte d’exécution distante

Quand un script PowerShell s’exécute sur une machine distante (via Invoke-Command ou des actions remote), le répertoire de départ n’est pas toujours celui attendu. Les sessions distantes démarrent souvent dans le répertoire utilisateur ou dans C:\Windows\System32.

Un Pushd vers un chemin réseau ou un dossier spécifique suivi d’un Popd dans finally reste la bonne approche, mais le debug interactif est limité. Les traces écrites dans un fichier log deviennent le seul outil de diagnostic fiable dans ce contexte. Remplacer Write-Debug par un Add-Content vers un fichier de log dédié garantit la persistance des informations, même si la session distante se ferme brutalement.

Pour les actions remote sur des parcs de machines, prévoir un Pushd conditionnel qui vérifie d’abord l’existence du répertoire cible avec Test-Path évite un échec muet. Si le chemin n’existe pas, le script peut sortir proprement au lieu d’empiler un répertoire invalide.

Checklist de debug pour un script avec Popd

Avant de lancer un script qui utilise Pushd/Popd, passer en revue ces points réduit la plupart des problèmes :

  • Chaque Pushd a un Popd correspondant, placé dans un bloc finally.
  • $ErrorActionPreference est défini à 'Stop' ou les commandes critiques portent -ErrorAction Stop.
  • Des traces Write-Debug affichent $PWD après chaque opération sensible.
  • Le nombre d’entrées dans la pile (Get-Location -Stack) est vérifié en début et en fin de script.
  • En exécution distante, les traces sont écrites dans un fichier log plutôt qu’envoyées sur la console.

Un script dont la pile de répertoires revient systématiquement à zéro en fin d’exécution ne laisse aucun effet de bord sur la session. C’est le critère le plus simple pour valider que le debug est terminé.

Les immanquables