Als je ooit hebt geprobeerd om op afstand opdrachten uit te voeren in PowerShell en steeds tegen problemen aanliep, is dat waarschijnlijk erg frustrerend. De cmdlet Invoke-Command is erg handig voor het uitvoeren van scripts of opdrachten op afstand, maar werkt alleen als WinRM (Windows Remote Management) correct is geconfigureerd. Meestal lopen mensen tegen problemen aan omdat WinRM niet is ingeschakeld op de doelmachine, of omdat firewalls inkomende verzoeken blokkeren. Het correct instellen hiervan kan aanvoelen als een kat-en-muisspel, vooral als je niet bekend bent met de exacte opdrachten of de manier om netwerkprofielen of firewallregels aan te passen. Deze handleiding beschrijft hoe je WinRM correct inschakelt, ervoor zorgt dat je netwerk is ingesteld voor beheer op afstand en hoe je vervolgens opdrachten op externe systemen kunt uitvoeren zonder al te veel moeite.
Hoe schakel ik PowerShell-remotebeheer (WinRM) in op Windows?
De WinRM-service inschakelen — een absolute noodzaak om opdrachten op afstand te laten werken
De belangrijkste reden waarom Invoke-Command geen verbinding kan maken? WinRM is niet ingeschakeld of niet geconfigureerd met de juiste netwerkregels. Allereerst moet de WinRM-service actief en geconfigureerd zijn. Om te controleren of WinRM al actief is en luistert, voert u de volgende opdracht uit in PowerShell op de doelmachine:
Get-Service -Name "*WinRM*" | fl WinRM, State Get-Item wsman:\localhost\Listener
Als het niet geconfigureerd is, geen probleem. Voer op de doelmachine het volgende commando uit:
winrm quickconfig
Deze opdracht doet een aantal dingen: de WinRM-service starten, deze instellen op automatisch starten, een standaardlistener aanmaken en firewall-uitzonderingen toevoegen. Soms Enable-PSRemoting -Forceis het voldoende om de opdracht gewoon als beheerder in PowerShell uit te voeren, vooral als u dit op afstand of via scripts probeert te doen. Houd er rekening mee dat u in sommige configuraties uw netwerkprofiel mogelijk moet aanpassen naar Privé of Domein, omdat PowerShell Remote standaard niet soepel werkt via openbare netwerken.
Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP" –RemoteAddress Any
Deze regel staat inkomend WinRM-verkeer toe, ongeacht het netwerkadres. Dit is handig als u te maken hebt met meerdere subnetsegmenten of een onorthodoxe netwerkconfiguratie. Onthoud dit, want Windows maakt het soms natuurlijk onnodig ingewikkeld.
Vertrouwde hosts — bij het werken met meerdere werkgroepen of IP-adressen
Als uw systemen zich niet in een domein bevinden of als u verbinding maakt via IP-adres, moet u die externe machines toevoegen aan uw lijst met vertrouwde hosts. Dit is een beetje een kwestie van “veiligheid uit gemak”, maar het is wel nodig. Voer het volgende commando uit:
Set-Item wsman:\localhost\Client\TrustedHosts -Value "192.168.1.201"
Of, als je je roekeloos voelt, sta dan gewoon alles toe:
Set-Item wsman:\localhost\Client\TrustedHosts -Value "*"
Vergeet niet dat u de WinRM-service daarna opnieuw moet starten:
Restart-Service WinRM
Met Invoke-Commands opdrachten uitvoeren op externe computers
Het uitvoeren van één enkel commando — eenvoudig, maar vereist de juiste configuratie.
Zodra WinRM is ingesteld en uw netwerkregels zijn geconfigureerd, hoeft u bij het gebruik van Invoke-Command alleen nog maar de doelmachine en de gewenste opdracht op te geven. Bijvoorbeeld:
Invoke-Command -ComputerName dc01 -ScriptBlock { Get-Service wuauclt }
Hiermee wordt de externe machine met de naam dc01 gevraagd of de Windows Update-service actief is. Verwacht dat de servicestatus wordt weergegeven. In één configuratie werkte dit probleemloos, in een andere kunnen er authenticatieproblemen optreden. Controleer daarom uw machtigingen en netwerkregels.
$cred = Get-Credential Invoke-Command -ComputerName dc01 -Credential $cred -ScriptBlock { Get-NetAdapter }
Dit is meestal handig als uw huidige gebruiker geen deel uitmaakt van de groepen ‘Extern beheer’ of ‘Beheer’ op de doelmachine. Houd er wel rekening mee dat er veel machtigingen bij betrokken zijn en dat PowerShell-beveiligingsbeleid soms bepaalde opdrachten op afstand blokkeert.
Meerdere commando’s of scripts op afstand uitvoeren — ja, dat kan.
Wil je meerdere dingen tegelijk doen? Scheid de opdrachten dan met een puntkomma binnen het ScriptBlock:
Invoke-Command -ComputerName dc01 -ScriptBlock { Get-TimeZone; Set-TimeZone -Name "Central Europe Standard Time" }
En als je ergens een script hebt opgeslagen, bijvoorbeeld C:\PS\CheckStatus.ps1, kun je het op afstand uitvoeren met:
Invoke-Command -ComputerName dc01 -FilePath "C:\PS\CheckStatus.ps1"
Op deze manier hoeft u scripts niet handmatig naar externe systemen te kopiëren en wordt het probleem van een mismatch in het uitvoeringsbeleid als het ware omzeild. Handig voor batchtaken of beheerscripts die u regelmatig uitvoert.
Opdrachten uitvoeren op meerdere computers tegelijk.
Parallelle commando’s voor een groot aantal servers
Als je een vloot servers beheert, is het uitvoeren van commando’s in serie een lastige klus. Gelukkig maakt Invoke-Command parallelle uitvoering mogelijk. Geef je servers gewoon op, gescheiden door komma’s:
Invoke-Command server1, server2, server3 -ScriptBlock { get-date }
Je kunt de namen ook in een array opslaan voor hergebruik:
$servers = @("server1", "server2", "server3") Invoke-Command -ComputerName $servers -ScriptBlock { get-date }
Invoke-Command -ComputerName (Get-Content c:\ps\servers.txt) -ScriptBlock { Restart-Service spooler }
Als u hostnamen uit Active Directory ophaalt, kunt u met de cmdlet Get-ADComputer filteren op bepaalde systemen:
$computers = (Get-ADComputer -Filter 'OperatingSystem -like "*Windows server*" -and Enabled -eq "true"').Name Invoke-Command -ComputerName $computers -ScriptBlock { Get-EventLog -LogName System -Newest 10 } -ErrorAction SilentlyContinue
En wat als een of meer doelcomputers offline of bezet zijn? De parameter -ErrorAction SilentlyContinue zorgt ervoor dat het script soepel blijft draaien. Bovendien kunt u de variabele PSComputerName in uw ScriptBlock gebruiken om te zien welke machine heeft gereageerd :
$results = Invoke-Command -ComputerName $computers -ScriptBlock { get-date } $results | Select-Object PSComputerName, *
Permanente PowerShell-verbindingen voor externe toegang — bespaar tijd en moeite
Creëer een sessie die lang blijft hangen.
Als u meerdere opdrachten uitvoert op dezelfde externe machine, is het handig om een sessie actief te houden in plaats van telkens opnieuw verbinding te maken. Zo maakt en gebruikt u een permanente sessie:
$session = New-PSSession -ComputerName Server01, Server02 Invoke-Command -Session $session -ScriptBlock { Get-ComputerInfo | select OsLastBootUpTime }
Als je klaar bent, sluit je de sessie af met:
Remove-PSSession $session
Deze configuratie kan aanzienlijk tijd besparen bij het beheren van meerdere servers, vooral als u veel commando’s uitvoert in een script of geplande taak. Houd er wel rekening mee dat sessies in het geheugen kunnen blijven hangen, dus sluit ze af wanneer ze niet meer nodig zijn. Daarnaast kan het zijn dat sommige configuraties wat extra beveiligingsaanpassingen of beleidswijzigingen vereisen om persistente sessies toe te staan.
Eerlijk gezegd kan het opzetten van PowerShell-beheer op afstand in het begin aanvoelen als een gevecht tegen een machtige baas, maar als het eenmaal lukt, is het ontzettend krachtig. Vergeet niet om de netwerk- en firewallregels te controleren en heb geduld met eventuele eigenaardigheden.