Chaque fois que vous vous connectez en RDP à une machine Windows juste pour « jeter un coup d’œil rapide », vous payez une taxe invisible : latence, changement de contexte, et la très réelle possibilité de cliquer sur la mauvaise chose sur le mauvais serveur. Les interfaces graphiques sont parfaites pour les démonstrations et catastrophiques pour la réponse aux incidents. Pendant une panne, une GUI est une machine à sous : vous tirez le levier en espérant que la prochaine fenêtre révélera la vérité.
Les one-liners PowerShell ne servent pas à être astucieux. Ils servent à être rapides, reproductibles et audités. Ils transforment « je pense que tout va bien » en « voici ce que dit le système ». Utilisez-les quotidiennement et vous passerez moins de temps à cliquer et plus de temps à prendre des décisions exploitables lors d’un postmortem.
Pourquoi les one-liners gagnent en production
Un bon one-liner fait trois choses : il interroge le système de référence, formate le résultat en quelque chose de raisonné, et rend l’action suivante évidente. C’est tout l’intérêt. Pas du golf de syntaxe.
La version GUI des tâches courantes est généralement :
- Se connecter à l’hôte approprié (ou au mauvais ; vous ne le saurez pas encore).
- Ouvrir le snap-in adéquat.
- Attendre qu’il se charge et rende l’interface.
- Cliquer, filtrer, trier, cliquer encore.
- Prendre une capture d’écran parce qu’il est difficile de faire un diff d’un screenshot.
La version PowerShell est :
- Exécuter une commande qui renvoie des objets structurés.
- Piper vers le tri, le filtrage, le groupement.
- Sauvegarder la sortie (ou l’exporter) pour pouvoir la comparer plus tard.
De plus : chaque fois que vous copiez/collez « ce que vous avez vu dans la GUI » dans un ticket, vous traduisez. La traduction introduit des erreurs. Les données les plus sûres sont celles que vous ne réinterprétez pas.
Idée paraphrasée de Gene Kim (auteur DevOps/ops) : les améliorations viennent du raccourcissement des boucles de rétroaction et de la visibilité du travail.
Les one-liners font les deux — quand vous les utilisez de façon consistante.
Blague #1 : Cliquer dans Server Manager pendant un incident, c’est comme déboguer avec une lampe de poche : techniquement possible, mais vous allez vous prendre les pieds dans quelque chose.
Faits et contexte historique (court, utile)
- PowerShell lancé en 2006 sous le nom de « Monad », construit sur des objets .NET plutôt que des flux de texte. C’est pourquoi son pipeline transporte des objets, pas des chaînes.
- WMI est antérieur à PowerShell ; de nombreuses vérifications PowerShell « modernes » enveloppent encore des classes WMI/CIM présentes depuis les années 1990.
- WinRM est devenu le cheval de trait du remote pour PowerShell, rapprochant l’administration Windows de workflows de type SSH — sauf avec plus de Kerberos et moins de surprises agréables.
- PowerShell 5.1 livré avec Windows 10/Server 2016 et reste le défaut sur beaucoup de serveurs ; PowerShell 7+ est séparé et multiplateforme.
- Get-WmiObject est legacy ;
Get-CimInstanceest le modèle plus récent (basé sur WS-Man), généralement plus ami des pare-feu et du remoting. - Les compteurs de performance sont anciens mais précieux ; ils restent l’un des moyens les plus fiables pour voir la pression CPU, mémoire, disque et réseau sous Windows.
- Les journaux d’événements sont la chose la plus proche d’un enregistreur de boîte noire pour Windows : imparfaits, mais lorsqu’ils sont utilisés avec des filtres ils valent mieux que « je jure que ça s’est passé ».
- Hyper-V et Storage Spaces se sont appuyés tôt sur PowerShell ; beaucoup d’actions GUI sont littéralement des wrappers autour de cmdlets.
- Group Policy et Active Directory disposent de cmdlets qui réduisent les « paramètres mystères » en transformant l’état des politiques en données interrogeables.
One-liners quotidiens : tâches, sorties et décision
Ci-dessous des commandes pratiques et exécutables. Chacune inclut (a) ce qu’elle fait, (b) ce que signifie la sortie, et (c) la décision que vous en tirez. Exécutez-les localement ou à distance (beaucoup acceptent -ComputerName ou fonctionnent via le remoting).
Remarque sur les blocs de code : Je les montre comme si exécutés depuis un shell. En pratique vous les lancerez dans PowerShell. Les commandes sont de vrais PowerShell.
1) Vérifier l’espace disque libre (rapide, triable, sans l’Explorateur)
cr0x@server:~$ powershell -NoProfile -Command "Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter,FileSystemLabel,@{n='SizeGB';e={[math]::Round($_.Size/1GB,1)}},@{n='FreeGB';e={[math]::Round($_.SizeRemaining/1GB,1)}},@{n='FreePct';e={[math]::Round(($_.SizeRemaining/$_.Size)*100,1)}} | Sort-Object FreePct | Format-Table -Auto"
DriveLetter FileSystemLabel SizeGB FreeGB FreePct
----------- -------------- ------ ------ -------
C OS 127.9 11.8 9.2
E Logs 500.0 210.5 42.1
F Data 2048.0 1530.2 74.7
Ce que ça signifie : FreePct est le premier indicateur de triage. En dessous d’environ 10–15 % sur les volumes système, considérez que des choses vont casser de manière étrange (patchs, fichiers temporaires, rotation de logs, dumps).
Décision : Si C: est bas, arrêtez « d’optimiser » et commencez à libérer de l’espace : vider les caches connus, faire la rotation des logs, déplacer les dumps, ou étendre le volume. Si un volume de données est bas, trouvez les plus gros consommateurs ensuite.
2) Trouver les répertoires les plus volumineux (réponse « qu’est-ce qui a mangé mon disque »)
cr0x@server:~$ powershell -NoProfile -Command "Get-ChildItem -Directory 'E:\' -Force | ForEach-Object { $s=(Get-ChildItem $_.FullName -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object Length -Sum).Sum; [pscustomobject]@{Path=$_.FullName; SizeGB=[math]::Round($s/1GB,2)} } | Sort-Object SizeGB -Descending | Select-Object -First 10 | Format-Table -Auto"
Path SizeGB
---- ------
E:\IISLogs 96.41
E:\App\Cache 51.08
E:\App\Temp 23.77
E:\Windows\Installer 12.30
Ce que ça signifie : C’est coûteux sur de grands arbres, mais c’est honnête. Utilisez-le quand vous avez besoin de faits, pas d’impressions.
Décision : Si les logs dominent, corrigez la rétention/la rotation. Si ce sont les caches/temp, confirmez s’il est sûr de les nettoyer et pourquoi ils croissent. Si Windows\Installer grossit, ne supprimez rien au hasard — nettoyez via les méthodes supportées.
3) Processus en tête CPU (Task Manager, mais scriptable)
cr0x@server:~$ powershell -NoProfile -Command "Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name,Id,CPU,WorkingSet64 | Format-Table -Auto"
Name Id CPU WorkingSet64
---- -- --- -----------
sqlservr 2440 8123.54 9126807552
w3wp 4012 1022.10 785334272
MsMpEng 1780 331.92 402653184
Ce que ça signifie : CPU ici est le temps CPU cumulé depuis le démarrage du processus, pas le « pourcentage actuel ». Il répond à « qui a brûlé du CPU sur la durée », ce qui est souvent ce qu’il faut réellement.
Décision : Si un même processus domine et que les performances sont mauvaises, passez aux compteurs de performance pour du CPU en temps réel et l’encombrement. Si c’est un antivirus, envisagez des exclusions (avec prudence) ou des horaires de scan.
4) Pression CPU en temps réel et file d’attente (évitez les suppositions)
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Processor(_Total)\% Processor Time','\System\Processor Queue Length' -SampleInterval 2 -MaxSamples 5 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto"
Path CookedValue
---- -----------
\\SERVER\processor(_total)\% processor time 87.12
\\SERVER\system\processor queue length 14
\\SERVER\processor(_total)\% processor time 92.44
\\SERVER\system\processor queue length 18
Ce que ça signifie : Un % Processor Time soutenu élevé plus une file d’attente qui reste élevée suggèrent une contention CPU. La file est particulièrement parlante sur les machines avec peu de cœurs.
Décision : Si la file reste élevée, identifiez la charge (processus chaud, tâches planifiées, antivirus, sauvegarde). Si c’est une machine virtuelle, vérifiez aussi la contention sur l’hôte. N’augmentez pas les vCPU sans mesurer le ready time de l’hôte (outil différent), mais traitez une file soutenue comme un signal réel.
5) Pression mémoire : available bytes et activité de pagination
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Memory\Available MBytes','\Memory\Pages/sec' -SampleInterval 2 -MaxSamples 5 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto"
Path CookedValue
---- -----------
\\SERVER\memory\available mbytes 312.00
\\SERVER\memory\pages/sec 86.50
\\SERVER\memory\available mbytes 280.00
\\SERVER\memory\pages/sec 95.00
Ce que ça signifie : Peu de MB disponibles plus un pages/sec soutenu suggèrent de la pagination active. La pagination n’est pas forcément mauvaise ; la pagination soutenue sous charge l’est.
Décision : Si la pagination est élevée pendant des plaintes de latence, vous avez soit (a) besoin de plus de RAM, (b) une fuite mémoire, ou (c) un cache qui a grandi parce que votre jeu de travail s’est étendu. Validez avec les working sets des processus et la télémétrie applicative.
6) Latence disque et longueur de file (les ingénieurs stockage vivent ici)
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\PhysicalDisk(_Total)\Avg. Disk sec/Read','\PhysicalDisk(_Total)\Avg. Disk sec/Write','\PhysicalDisk(_Total)\Current Disk Queue Length' -SampleInterval 2 -MaxSamples 5 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto"
Path CookedValue
---- -----------
\\SERVER\physicaldisk(_total)\avg. disk sec/read 0.045
\\SERVER\physicaldisk(_total)\avg. disk sec/write 0.112
\\SERVER\physicaldisk(_total)\current disk queue length 23
Ce que ça signifie : 45ms en lecture et 112ms en écriture avec une file de 23, ce n’est pas « acceptable ». Pour beaucoup de charges serveur, vous visez des latences à un chiffre en millisecondes. Il y a des exceptions, mais elles doivent être intentionnelles.
Décision : Si latence et file sont élevées, identifiez le volume occupé, puis le processus chargé. Sur des VM, confirmez si c’est côté invité ou hôte. Ne poursuivez pas le CPU si le disque est en train de se noyer.
7) Qui martèle le disque ? (I/O par processus)
cr0x@server:~$ powershell -NoProfile -Command "Get-Process | Select-Object Name,Id,@{n='ReadMB';e={[math]::Round($_.IOReadBytes/1MB,1)}},@{n='WriteMB';e={[math]::Round($_.IOWriteBytes/1MB,1)}} | Sort-Object WriteMB -Descending | Select-Object -First 10 | Format-Table -Auto"
Name Id ReadMB WriteMB
---- -- ------ -------
sqlservr 2440 5120.3 9032.8
backup 3112 120.1 2201.4
w3wp 4012 980.7 610.2
Ce que ça signifie : Ce sont des compteurs cumulés. Ils pointent rapidement vers les suspects habituels : moteurs de base de données, agents de sauvegarde, indexation, antivirus, logs devenus fous.
Décision : Si la sauvegarde ou l’AV domine pendant les heures ouvrées, corrigez la planification. Si les logs dominent, réduisez le niveau de log ou envoyez-les sur un autre volume.
8) Vérifier quels ports écoutent (la GUI n’est pas invitée)
cr0x@server:~$ powershell -NoProfile -Command "Get-NetTCPConnection -State Listen | Select-Object LocalAddress,LocalPort,OwningProcess | Sort-Object LocalPort | Select-Object -First 20 | Format-Table -Auto"
LocalAddress LocalPort OwningProcess
------------ --------- -------------
0.0.0.0 80 4012
0.0.0.0 135 968
0.0.0.0 443 4012
0.0.0.0 3389 1156
Ce que ça signifie : Cela répond à « qui écoute réellement », pas à « ce que nous pensons devoir tourner ». Associez-le ensuite aux noms de processus.
Décision : Si un port critique n’écoute pas, enquêtez sur le service/l’application. Si un port inattendu écoute, vous avez soit une dérive de configuration soit une compromission — prenez-le au sérieux.
9) Mapper les ports écoutés aux noms de processus (rendre actionnable)
cr0x@server:~$ powershell -NoProfile -Command "Get-NetTCPConnection -State Listen | ForEach-Object { $p=Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue; [pscustomobject]@{Port=$_.LocalPort; Process=$p.Name; PID=$_.OwningProcess; Address=$_.LocalAddress} } | Sort-Object Port | Format-Table -Auto"
Port Process PID Address
---- ------- --- -------
80 w3wp 4012 0.0.0.0
135 svchost 968 0.0.0.0
443 w3wp 4012 0.0.0.0
3389 TermService 1156 0.0.0.0
Ce que ça signifie : Maintenant « le port 443 est down » devient « w3wp n’est pas lancé », différence entre panique et réparation.
Décision : Si le PID n’est pas celui attendu, vérifiez la configuration du service, les bindings IIS ou les paramètres de lancement de l’application. Si c’est inconnu, n’en restez pas là — identifiez le chemin binaire.
10) Vérifier qu’un service Windows tourne (et pourquoi il ne tourne pas)
cr0x@server:~$ powershell -NoProfile -Command "Get-Service -Name 'Spooler','W32Time','WinRM' | Select-Object Name,Status,StartType | Format-Table -Auto"
Name Status StartType
---- ------ ---------
Spooler Running Automatic
W32Time Running Automatic
WinRM Running Automatic
Ce que ça signifie : C’est de l’hygiène de base. Si WinRM est désactivé, votre journée d’opérations à distance devient une journée de voyage.
Décision : Si un service critique est arrêté, vérifiez les changements récents et les journaux système avant de le redémarrer. Les redémarrages à l’aveugle peuvent cacher des preuves et répéter les échecs.
11) Récupérer les 50 dernières erreurs système (Event Viewer est un labyrinthe)
cr0x@server:~$ powershell -NoProfile -Command "Get-WinEvent -FilterHashtable @{LogName='System'; Level=2} -MaxEvents 50 | Select-Object TimeCreated,Id,ProviderName,Message | Format-Table -Wrap"
TimeCreated Id ProviderName Message
----------- -- ------------ -------
02/05/2026 09:14:02 11 Disk The driver detected a controller error on \Device\Harddisk2\DR2.
02/05/2026 09:11:47 7031 Service Control Manager The SQLAgent$INST service terminated unexpectedly...
Ce que ça signifie : Level=2 est « Error ». Vous cherchez des motifs : erreurs disque/contrôleur, crashes de services, échecs de synchronisation temporelle, resets réseau.
Décision : Les erreurs disque/contrôleur vous déplacent du débogage applicatif vers l’intégrité des données et le chemin matériel. Les crashes de services vous poussent à rechercher « qu’est-ce qui a changé » et les dumps.
12) Récupérer les erreurs applicatives pour un fournisseur spécifique (triage ciblé)
cr0x@server:~$ powershell -NoProfile -Command "Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='Application Error'} -MaxEvents 20 | Select-Object TimeCreated,Id,Message | Format-Table -Wrap"
TimeCreated Id Message
----------- -- -------
02/05/2026 09:12:10 1000 Faulting application name: w3wp.exe...
Ce que ça signifie : C’est le fil « pourquoi ça a planté ». Vous verrez les modules fautifs, les codes d’exception et les noms d’applications.
Décision : Si le même module plante après un patch ou un changement de config, restaurez ou mettez à jour. Si c’est aléatoire, suspectez corruption mémoire, drivers défectueux ou dépendances instables.
13) Vérifier les redémarrages récents et pourquoi (la vérité est dans les logs)
cr0x@server:~$ powershell -NoProfile -Command "Get-WinEvent -FilterHashtable @{LogName='System'; Id=1074} -MaxEvents 10 | Select-Object TimeCreated,Message | Format-Table -Wrap"
TimeCreated Message
----------- -------
02/04/2026 23:01:12 The process C:\Windows\System32\svchost.exe (SERVER) has initiated the restart...
Ce que ça signifie : L’ID d’événement 1074 enregistre souvent les redémarrages initiés par un utilisateur ou un processus et inclut la chaîne de raison si fournie.
Décision : Si les redémarrages sont inattendus, ne traitez plus l’uptime comme la météo. Lie les redémarrages aux fenêtres de patch, à l’automatisation ou aux opérateurs. Corrigez le processus, pas le symptôme.
14) Vérifier les mises à jour installées (niveau de patch sans cliquer)
cr0x@server:~$ powershell -NoProfile -Command "Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 10 HotFixID,InstalledOn,Description | Format-Table -Auto"
HotFixID InstalledOn Description
------- ----------- -----------
KB5034765 02/02/2026 Update
KB5034123 01/15/2026 Security Update
Ce que ça signifie : Confirmation rapide de la récence des patchs. Pas parfait (certains mécanismes d’update n’apparaissent pas proprement), mais bon premier passage.
Décision : Si un bug corrèle avec un KB récent, vous avez une hypothèse de rollback crédible. Si un serveur est à la traîne, cessez de prétendre qu’il est « stable » ; il est juste non patché.
15) Valider la résolution DNS et le type d’enregistrement (éviter le théâtre « le réseau est en panne »)
cr0x@server:~$ powershell -NoProfile -Command "Resolve-DnsName -Name 'app01.corp.local' -Type A | Select-Object Name,Type,IPAddress | Format-Table -Auto"
Name Type IPAddress
---- ---- ---------
app01.corp.local A 10.40.12.21
Ce que ça signifie : Si cela échoue ou renvoie la mauvaise IP, la moitié de votre « panne applicative » est en réalité une résolution de noms.
Décision : Mauvaise IP signifie DNS obsolète ou enregistrement erroné ; corrigez les attentes de TTL, l’intégration DHCP/DNS ou les enregistrements manuels. Pas de réponse signifie investiguer les serveurs DNS, le forwarding ou le pare-feu.
16) Tester un service TCP de bout en bout (ping n’est pas un contrôle de santé)
cr0x@server:~$ powershell -NoProfile -Command "Test-NetConnection -ComputerName 'app01.corp.local' -Port 443 | Select-Object ComputerName,RemotePort,TcpTestSucceeded,SourceAddress | Format-List"
ComputerName : app01.corp.local
RemotePort : 443
TcpTestSucceeded : True
SourceAddress : 10.40.10.55
Ce que ça signifie : Cela répond à « puis-je établir une connexion TCP d’ici vers là ». Ce n’est pas une validation des certificats TLS ou de la justesse applicative, mais ça réduit rapidement le périmètre.
Décision : Si TcpTestSucceeded est faux, vérifiez règles de firewall, routage, status du listener et load balancers. Si vrai, montez la pile : TLS, HTTP, auth, logs applicatifs.
17) Trouver les tâches planifiées échouées (les saboteurs silencieux)
cr0x@server:~$ powershell -NoProfile -Command "Get-ScheduledTask | Get-ScheduledTaskInfo | Where-Object {$_.LastTaskResult -ne 0} | Sort-Object LastRunTime -Descending | Select-Object -First 15 TaskName,LastRunTime,LastTaskResult | Format-Table -Auto"
TaskName LastRunTime LastTaskResult
-------- ----------- --------------
DailyLogRotate 02/05/2026 01:00:01 2147942401
BackupSnapshot 02/05/2026 02:00:03 1
Ce que ça signifie : Les résultats non nuls indiquent des échecs. Le code numérique correspond souvent à « fichier introuvable », « accès refusé », etc.
Décision : Si les tâches d’entretien échouent, attendez-vous à des incidents de disque plein et à une dégradation progressive par milliers de fichiers. Corrigez permissions, chemins et comptes de service avant le prochain pic.
18) Vérifier les partages SMB et qui est connecté (réalité du serveur de fichiers)
cr0x@server:~$ powershell -NoProfile -Command "Get-SmbShare | Select-Object Name,Path,Description | Format-Table -Auto"
Name Path Description
---- ---- -----------
Finance D:\Finance Finance share
Profiles E:\Profiles User profiles
cr0x@server:~$ powershell -NoProfile -Command "Get-SmbSession | Select-Object ClientComputerName,ClientUserName,NumOpens,Dialect | Sort-Object NumOpens -Descending | Select-Object -First 10 | Format-Table -Auto"
ClientComputerName ClientUserName NumOpens Dialect
------------------ -------------- -------- -------
WS123 CORP\j.smith 42 3.1.1
Ce que ça signifie : Cela confirme « quelqu’un utilise le partage en ce moment » avant une maintenance, et aide à identifier un client provoquant des verrous excessifs.
Décision : Si un client a un nombre absurde d’ouvertures, enquêtez sur ce poste/application. Si vous devez redémarrer un partage, coordonnez-vous avec les utilisateurs plutôt que de saboter leur journée.
19) Contrôle des permissions : qui a accès à un dossier ?
cr0x@server:~$ powershell -NoProfile -Command "(Get-Acl 'D:\Finance').Access | Select-Object IdentityReference,FileSystemRights,AccessControlType,IsInherited | Format-Table -Auto"
IdentityReference FileSystemRights AccessControlType IsInherited
----------------- ---------------- ----------------- -----------
CORP\Finance-Users Modify, Synchronize Allow True
CORP\Domain Admins FullControl Allow True
Ce que ça signifie : Cela montre les entrées ACL effectives, y compris l’héritage. C’est la différence entre « ça devrait marcher » et « ça marche vraiment ».
Décision : Si l’accès manque, corrigez l’appartenance aux groupes ou l’héritage au bon niveau. Évitez les ACL one-off pour des utilisateurs à moins d’aimer l’archéologie future.
20) À distance : exécuter un contrôle de santé sur plusieurs serveurs (flotte, pas des animaux de compagnie)
cr0x@server:~$ powershell -NoProfile -Command "$servers='web01','web02','web03'; Invoke-Command -ComputerName $servers -ScriptBlock { [pscustomobject]@{ ComputerName=$env:COMPUTERNAME; UptimeDays=[math]::Round((New-TimeSpan -Start (Get-CimInstance Win32_OperatingSystem).LastBootUpTime -End (Get-Date)).TotalDays,1); FreeC=[math]::Round((Get-PSDrive C).Free/1GB,1) } } | Format-Table -Auto"
ComputerName UptimeDays FreeC
------------ --------- -----
WEB01 12.4 18.7
WEB02 2.1 6.3
WEB03 56.0 22.9
Ce que ça signifie : Une commande, trois machines, données cohérentes. Aussi : WEB02 a peu d’espace libre et a redémarré récemment. Cette corrélation est rarement accidentelle.
Décision : Priorisez l’outlier. Ne lissez pas les résultats jusqu’à l’endormissement. Corrigez WEB02 en premier, puis demandez-vous pourquoi il se comporte différemment.
Blague #2 : La GUI affiche « Non répond » comme si c’était une limite personnelle. Le serveur le dit parce qu’il est en feu.
Playbook de diagnostic rapide : quoi vérifier en premier/deuxième/troisième
Voici la séquence que j’utilise quand quelqu’un dit « l’app est lente » ou « le serveur meurt » et que le seul détail que vous avez est un nom d’hôte et de l’angoisse. L’objectif n’est pas de tout résoudre en 60 secondes ; l’objectif est de trouver la classe de goulot pour arrêter de deviner.
Premier : confirmer que la plainte est réelle et bien cadrée
- Côté client : pouvez-vous vous connecter au port du service ?
cr0x@server:~$ powershell -NoProfile -Command "Test-NetConnection -ComputerName 'app01.corp.local' -Port 443 | Select-Object TcpTestSucceeded,RemoteAddress,RemotePort | Format-List" TcpTestSucceeded : True RemoteAddress : 10.40.12.21 RemotePort : 443Interprétation : Si le TCP échoue, c’est réseau/listener/LB/sécurité. Si le TCP réussit, avancez vers l’intérieur.
- Sur le serveur : le port pertinent écoute-t-il et est-il possédé par le bon processus ?
cr0x@server:~$ powershell -NoProfile -Command "Get-NetTCPConnection -State Listen -LocalPort 443 | ForEach-Object { $p=Get-Process -Id $_.OwningProcess; [pscustomobject]@{Port=$_.LocalPort; Process=$p.Name; PID=$p.Id} } | Format-Table -Auto" Port Process PID ---- ------- --- 443 w3wp 4012Interprétation : Pas de listener signifie que l’app est arrêtée. Mauvais processus signifie mauvaise config ou pire.
Deuxième : classifier le goulot (CPU, mémoire, disque, réseau, ou « app »)
- Pression CPU : % processor time + file d’attente.
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Processor(_Total)\% Processor Time','\System\Processor Queue Length' -SampleInterval 2 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto" Path CookedValue ---- ----------- \\SERVER\processor(_total)\% processor time 91.33 \\SERVER\system\processor queue length 16Décision : Si le CPU est saturé avec file d’attente, identifiez le processus chaud et ce qui l’a déclenché (déploiement, job, scan, tempête de retries).
- Pression mémoire : available MB + pages/sec.
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Memory\Available MBytes','\Memory\Pages/sec' -SampleInterval 2 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto" Path CookedValue ---- ----------- \\SERVER\memory\available mbytes 190.00 \\SERVER\memory\pages/sec 120.00Décision : Si vous paginez beaucoup, attendez-vous à des latences partout. Capturez les données mémoire des processus ; envisagez un redémarrage contrôlé seulement après collecte des preuves.
- Pression disque : latence + file.
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\PhysicalDisk(_Total)\Avg. Disk sec/Read','\PhysicalDisk(_Total)\Avg. Disk sec/Write','\PhysicalDisk(_Total)\Current Disk Queue Length' -SampleInterval 2 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto" Path CookedValue ---- ----------- \\SERVER\physicaldisk(_total)\avg. disk sec/read 0.060 \\SERVER\physicaldisk(_total)\avg. disk sec/write 0.140 \\SERVER\physicaldisk(_total)\current disk queue length 27Décision : Si le disque est mauvais, arrêtez de chercher des « requêtes lentes » tant que vous n’avez pas confirmé que le stockage n’est pas le limiteur. La latence en amont est souvent la conséquence en aval.
Troisième : décider « atténuer maintenant » versus « enquêter »
- Atténuer maintenant quand l’impact utilisateur est sévère et que la correction est réversible : arrêter un job qui part en vrille, limiter une file, basculer, ajouter une capacité temporaire, déplacer des logs.
- Enquêter d’abord quand l’action détruit des preuves : reboots, redémarrages de service, effacement de logs, suppression d’arbres temporaires sans snapshots.
Utilisez les commandes ci-dessus pour appuyer cette décision, puis notez ce que vous avez vu. Si vous ne pouvez pas expliquer votre chaîne d’actions plus tard, vous n’avez pas vraiment opéré — vous avez joué un rôle.
Trois mini-récits d’entreprise (ce qui a mal tourné, ce qui nous a sauvés)
Mini-récit 1 : l’incident causé par une mauvaise hypothèse
Nous avons hérité d’un serveur de fichiers Windows qui « n’avait jamais de problèmes ». La croyance partagée de l’équipe était que les alertes disque prendraient en charge tout ce qui est sérieux. Le monitoring a alerté — finalement. Le problème était l’hypothèse que « espace disque » signifiait « espace libre », et que c’était tout ce qui importait.
Un lundi matin, une vague de tickets est arrivée : profils itinérants qui échouent, traitement de stratégie de groupe lent, crashes aléatoires d’applications lors de connexions d’utilisateurs. L’astreinte a fait le classique : RDP, ouvrir l’Explorateur, voir que C: avait quelques GB libres, et déclarer « le disque n’est pas plein ». Puis ils ont redémarré quelques services. Ça donnait l’impression d’être productif. Ça n’a rien résolu.
Nous avons exécuté des one-liners : espace libre des volumes (plutôt ok), puis journaux d’événements (pas ok). Le journal Système montrait des erreurs disque/contrôleur et des avertissements NTFS. Le lecteur n’était pas plein ; il était malade. La latence grimpait, les écritures se bloquaient, et le serveur de fichiers faisait en quelque sorte de l’I/O au ralenti.
L’hypothèse erronée était subtile : « l’espace est le seul problème disque ». La santé d’un disque n’est pas une variable unique ; c’est la latence, la file d’attente, les taux d’erreur et la stabilité du chemin. Quand le stockage commence à échouer, Windows ne vous donne pas toujours une popup sympathique. Il vous donne des timeouts et un risque de corruption.
La correction n’a pas été un redémarrage héroïque. Nous avons basculé les charges, engagé l’équipe stockage, et remplacé un chemin HBA défectueux. La leçon est restée : les vérifications de capacité sont nécessaires ; les vérifications du comportement du disque préviennent les désastres.
Mini-récit 2 : l’optimisation qui s’est retournée
Un ingénieur bien intentionné voulait accélérer les recherches de logs. Il a activé le logging verbeux de l’application, puis écrit une tâche planifiée pour compresser les logs toutes les heures et les déplacer vers un partage central. Le plan semblait raisonnable : fichiers plus petits, dépannage centralisé, moins d’utilisation disque.
En production, c’est devenu une panne lente. Le job de compression lançait en même temps sur tous les serveurs, à l’heure pile. Le CPU a bondi, les écritures disque ont explosé, et le partage central a été submergé. Les performances metadata du partage se sont effondrées parce que des milliers de fichiers étaient créés, renommés et supprimés en rafales.
Les utilisateurs ne se plaignaient pas de la « compression des logs ». Ils se plaignaient que l’app « se fige toutes les heures pendant quelques minutes ». Ce symptôme prête facilement à une mauvaise analyse. Les gens ont blâmé les pauses GC, les verrous base de données, et le jitter réseau. Le vrai coupable était une « optimisation » qui créait de la contention synchronisée.
Nous l’avons prouvé avec deux vérifications rapides : longueur de file disque et I/O par processus. Le processus de compression n’était pas le premier consommateur CPU toute la journée, mais il dominait les écritures pendant la fenêtre de plainte. C’est le type de preuve qui met fin aux débats.
Nous avons corrigé en échelonnant les horaires avec du jitter, réduisant la verbosité, et modifiant le pipeline : compresser une fois par jour hors hôte, pas toutes les heures sur chaque nœud. Les optimisations qui ignorent les patterns de contention ne sont pas des optimisations ; ce sont des attaques par déni de service distribuées avec de meilleures intentions.
Mini-récit 3 : la pratique ennuyeuse mais correcte qui a sauvé la mise
Une autre équipe exécutait une petite pratique disciplinée : chaque matin, ils lançaient un court script « pulse serveur » sur leur flotte. Uptime, espace libre, date du dernier patch, et principales erreurs du journal Système. Ils ne le faisaient pas parce qu’ils adoraient les dashboards. Ils le faisaient parce qu’ils détestaient les surprises.
Un mardi, le pulse a signalé un serveur isolé avec une combinaison étrange : espace libre en chute sur E:, échecs de tâches planifiées, et avertissements répétés d’un agent de sauvegarde. Personne ne se plaignait encore. C’est le point clé : le système chuchotait avant de hurler.
Ils ont enquêté sur les échecs de tâches planifiées et découvert que la tâche de rotation des logs avait commencé à échouer après un changement de permissions. Les logs s’accumulaient, la sauvegarde échouait sur des répertoires de logs massifs, et le volume était projeté plein dans les 24 heures.
Ils ont corrigé l’ACL, exécuté la rotation manuellement une fois, et validé que la tâche planifiée réussissait. Le serveur n’a jamais atteint 0 octet libre, la sauvegarde a récupéré, et l’entreprise n’a rien remarqué.
Cela n’est pas sexy. Ça ne gagne pas de prix d’architecture. Ça fait gagner le sommeil de l’astreinte. La pratique ennuyeuse n’était pas le script ; c’était l’habitude de regarder les mêmes signaux chaque jour et de traiter les déviations comme réelles.
Erreurs courantes : symptômes → cause racine → correction
1) « Le serveur est lent » mais le CPU semble correct
Symptôme : L’utilisation CPU est modérée, pourtant les utilisateurs subissent des timeouts et des gels.
Cause racine : Latence disque/file d’attente ou pression de pagination mémoire. Le CPU attend, il ne travaille pas.
Correction : Vérifiez d’abord les compteurs disque et mémoire, pas les impressions de Task Manager.
cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\PhysicalDisk(_Total)\Avg. Disk sec/Read','\PhysicalDisk(_Total)\Current Disk Queue Length','\Memory\Pages/sec' -SampleInterval 2 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue | Format-Table -Auto"
Path CookedValue
---- -----------
\\SERVER\physicaldisk(_total)\avg. disk sec/read 0.080
\\SERVER\physicaldisk(_total)\current disk queue length 31
\\SERVER\memory\pages/sec 110
2) « Le port est ouvert » parce que le ping répond
Symptôme : Quelqu’un affirme que le service est joignable parce que l’ICMP répond.
Cause racine : Le ping teste l’ICMP, pas la disponibilité applicative. Pare-feux, load balancers et listeners se moquent de votre ping.
Correction : Testez le port TCP réel depuis le segment réseau réel du client.
cr0x@server:~$ powershell -NoProfile -Command "Test-NetConnection -ComputerName 'db01.corp.local' -Port 1433 | Select-Object TcpTestSucceeded,RemoteAddress,RemotePort | Format-List"
TcpTestSucceeded : False
RemoteAddress : 10.40.20.10
RemotePort : 1433
3) « Le service tourne » mais l’app est quand même down
Symptôme : Get-Service indique Running ; les utilisateurs ne peuvent toujours pas se connecter.
Cause racine : Le service est vivant mais n’écoute pas, est bloqué, ou lié à la mauvaise interface/port. Ou bien une dépendance (certificat, backend) est cassée.
Correction : Validez le listener et mappez-le au processus ; vérifiez les erreurs dans le journal Application.
cr0x@server:~$ powershell -NoProfile -Command "Get-NetTCPConnection -State Listen -LocalPort 443 | Measure-Object | Select-Object Count"
Count
-----
0
4) « On a nettoyé l’espace disque » et maintenant l’app ne démarre plus
Symptôme : Après suppression de « junk », les services échouent, les installateurs cassent, ou les patchs échouent.
Cause racine : Quelqu’un a supprimé des fichiers qui n’étaient pas du junk (cache d’installateur, état d’app, bases, sauvegardes de config IIS).
Correction : Soyez précis : identifiez la source de croissance, corrigez la rétention, et supprimez uniquement des cibles connues comme sûres. Si vous devez supprimer, faites un snapshot d’abord (snapshot VM ou copie shadow selon la politique).
5) Le remoting fonctionne sur certains serveurs mais pas d’autres
Symptôme : Invoke-Command échoue de façon intermittente sur une flotte.
Cause racine : WinRM désactivé, différences de firewall, erreurs de résolution DNS, ou configuration d’hôtes non approuvés.
Correction : Standardisez : assurez-vous que le service WinRM est en marche, que les règles firewall sont cohérentes, et que le DNS est correct. Évitez de mettre « TrustedHosts = * » comme pansement paresseux en production.
6) Le tri de la sortie semble incorrect
Symptôme : Vous triez par une colonne et l’ordre est absurde (ex. « 100 » avant « 9 »).
Cause racine : Vous avez formaté trop tôt ; vous avez transformé des objets en chaînes avec Format-Table avant de trier.
Correction : Triez les objets d’abord, formatez à la fin.
Listes de contrôle / plan étape par étape
Routine ops quotidienne de 10 minutes (faites-la, n’en débattez pas)
- Vérification d’espace : trouvez les volumes sous 15 % de libre ; créez un ticket avant que ce soit urgent.
- Scan d’erreurs : les 50 dernières erreurs Système ; identifiez les répétitions (disque, resets NIC, crashes de services).
- Sanity patch : confirmez les hotfix récents ; signalez les machines qui divergent.
- Échecs de tâches : tâches planifiées avec résultats non nuls ; corrigez les ennuyeuses en premier.
- Contrôle des outliers : exécutez le même one-liner sur la flotte et chassez le serveur étrange.
Checklist de réponse incident (premiers 15 minutes)
- Confirmer la joignabilité :
Test-NetConnectionvers le port du service depuis un segment réseau pertinent. - Confirmer listener/process :
Get-NetTCPConnection+ mapping processus. - Classer le goulot : file CPU, pagination mémoire, latence/queue disque.
- Capturer des preuves : top processes, slice du journal d’événements, échantillons de compteurs.
- Atténuer en sécurité : uniquement après pouvoir justifier l’action avec des données observées.
Checklist de vérification post-change (après déploiements/patchs)
- Confirmer l’état des services : services attendus en Running, bons types de démarrage.
- Confirmer les ports : ports attendus à l’écoute, possédés par les binaires attendus.
- Confirmer les logs : scanner Application et System pour les erreurs depuis le moment du déploiement.
- Confirmer les performances : comparer des snapshots de compteurs (latence, files) au baseline.
FAQ
1) Dois-je utiliser Windows PowerShell 5.1 ou PowerShell 7 ?
Utilisez 5.1 quand vous avez besoin de compatibilité maximale avec d’anciens modules sur Windows Server. Utilisez 7 quand vous contrôlez l’environnement et voulez des fonctionnalités modernes et la parité multiplateforme. Dans les entreprises mixtes, vous finirez par utiliser les deux.
2) Pourquoi continuer à utiliser les compteurs de performance plutôt que seulement les processus « top » ?
Parce que les compteurs vous disent la pression (files d’attente, latence, pagination) tandis que les listes de processus vous donnent l’attribution. Il faut les deux. Si vous regardez seulement les processus, vous pouvez manquer complètement la vraie classe de goulot.
3) Est-ce que Get-WmiObject est mort ?
Pas mort, juste legacy. Préférez Get-CimInstance pour les patterns de script récents, surtout avec le remoting. Mais en pratique vous verrez encore WMI partout, y compris dans des scripts fournisseurs.
4) Pourquoi certains compteurs affichent des nombres qui ne correspondent pas à ce que je vois dans le Gestionnaire des tâches ?
L’échantillonnage et les définitions diffèrent. Le Gestionnaire des tâches montre souvent des valeurs instantanées ou moyennées ; les compteurs peuvent être échantillonnés à des intervalles différents et représenter différents modèles de calcul. Rendre votre intervalle d’échantillonnage explicite et prenez plusieurs échantillons.
5) Puis-je exécuter ces one-liners sur des serveurs distants sans RDP ?
Oui, avec le remoting PowerShell (Invoke-Command) quand WinRM est configuré. Pour certains contrôles réseau vous pouvez aussi interroger depuis votre machine (ex. Test-NetConnection). Standardisez WinRM tôt ; ça rapporte chaque semaine.
6) Comment éviter les problèmes de « formatage trop tôt » ?
Règle : faites tout le filtrage/tri/groupement tant que le pipeline contient encore des objets, puis formatez à la fin. Si vous pipez vers Format-Table, vous mettez fin au flux de données.
7) Les one-liners sont-ils sûrs à coller en production ?
Les one-liners en lecture seule sont généralement sûrs. Tout ce qui supprime, arrête des services, redémarre ou change la config doit être promu en script avec journalisation et mode dry-run. Si vous ne savez pas expliquer son rayon d’impact, ne l’exécutez pas.
8) Quelle est la façon la plus rapide de détecter « ce serveur est différent » dans un cluster ?
Exécutez la même commande sur tous les nœuds et triez par la métrique qui vous importe (espace libre, uptime, nombre d’erreurs, valeurs de compteurs). Les outliers cachent la vérité.
9) Ma commande est lente (comme les vérifications de taille de répertoire). Que faire ?
N’utilisez les vérifications coûteuses que lorsque c’est nécessaire, et restreignez-les : chemins plus petits, moins de cibles récursives, ou exécutez-les hors heures. Pour la surveillance continue, instrumentez les logs et les quotas plutôt que de rescanner le système de fichiers à chaque fois.
Prochaines étapes pratiques
Faites ceci demain matin :
- Choisissez cinq serveurs que vous touchez chaque semaine. Exécutez le one-liner de flotte pour uptime et espace libre. Trouvez l’outlier et corrigez-le.
- Ajoutez un échantillon compteur de 2 minutes pour la file CPU, la pagination et la latence disque à vos notes d’incident standard. Cessez de diagnostiquer depuis des captures d’écran.
- Construisez (ou empruntez) un petit script « pulse check » à partir des commandes ci-dessus et exécutez-le quotidiennement. Le but n’est pas la perfection ; c’est de remarquer la dérive avant qu’elle ne devienne une panne.
- Quand vous avez besoin de la GUI, utilisez-la intentionnellement : pour la configuration profonde, pas pour la découverte panique.
Si vous voulez un test décisif pour savoir si votre pratique d’exploitation s’améliore : mesurez à quelle fréquence vous pouvez répondre « qu’est-ce qui a changé ? » avec des preuves en moins de cinq minutes. Les one-liners ne sont pas magiques. Ce sont du levier.