Använda en-till-många-fjärrkommunikation med hjälp av Windows PowerShell

Slutförd

Med en-till-många-fjärrkommunikation kan du skicka ett enda kommando till flera datorer parallellt. Varje dator kör det kommando som du överför, serialiserar resultaten till XML och överför dessa resultat tillbaka till datorn. Datorn deserialiserar sedan XML till objekt och placerar dem i Windows PowerShell-pipelinen. När du gör detta läggs flera egenskaper till i varje objekt, inklusive en PSComputerName-egenskap som anger vilken dator varje resultat kommer från. Med den egenskapen kan du sortera, gruppera och filtrera baserat på datornamn.

Du kan använda en-till-många-fjärrkommunikation med hjälp av två olika tekniker:

  • Invoke-Command – ComputerName name1,name2 – ScriptBlock { command }. Den här tekniken skickar kommandot (eller kommandona) som finns i skriptblocket till de datorer som du listar. Den här tekniken är användbar för att skicka ett eller två kommandon. flera kommandon avgränsas med ett semikolon.
  • Invoke-Command – ComputerName name1,name2 – FilePath filepath. Den här tekniken skickar innehållet i en skriptfil med filnamnstillägget .ps1 till de datorer som du listar. Den lokala datorn öppnar filen och läser dess innehåll. Fjärrdatorerna behöver dock inte ha direkt åtkomst till filen. Den här tekniken är användbar för att skicka en stor fil med kommandon, till exempel ett fullständigt skript.

Kommentar

I alla skriptblock (inklusive skriptblocket som tillhandahålls till parametern –ScriptBlock ) kan du använda ett semikolon för att separera flera kommandon. Kör till exempel { Get-Service ; Get-Process }Get-Service och kör sedan Get-Process.

Begränsning

För att hjälpa dig att hantera resurserna på den lokala datorn innehåller PowerShell en begränsningsfunktion per kommando som gör att du kan begränsa antalet samtidiga fjärranslutningar som upprättats för varje kommando. Som standard ansluter Windows PowerShell endast till 32 datorer samtidigt. Om du listar fler än 32 datorer placeras anslutningarna till de andra datorerna i kö. När sessioner till några av datorerna från den första batchen har slutförts och deras resultat returneras initieras anslutningar till datorerna i nästa batch.

Du kan ändra det här beteendet med parametern –ThrottleLimit i Invoke-Command. Om du höjer antalet läggs ingen extra belastning på fjärrdatorerna. Den lägger dock en extra belastning på datorn där Invoke-Command anropades. Den använder också mer bandbredd. Varje samtidig anslutning är i princip en tråd i Windows PowerShell. Att öka antalet datorer förbrukar därför minne och processorhastighet på den lokala datorn.

Skicka värden

Skriptblocket eller filinnehållet överförs som literaltext till de fjärrdatorer som kör dem exakt som de är. Datorn parsar inte skriptblocket eller filen där Invoke-Command kördes. Överväg följande kommandoexempel:

$var = 'BITS'
Invoke-Command –ScriptBlock { Get-Service –Name $var } –Computer LON-DC1

I det här scenariot anges variabeln $var på den lokala datorn i stället för att inkluderas i skriptblocket som ska köras på LON-DC1. Med andra ord är $var inte definierat eller inställt i fjärrsessionen för PowerShell till LON-DC1, vilket är ett vanligt misstag som nya administratörer av Windows PowerShell ofta gör.

Köra kommandon lokalt och via fjärranslutning

Var uppmärksam på de kommandon som du omger i skriptblocket, som skickas till fjärrdatorn. Kom ihåg att den lokala datorn inte bearbetar något innehåll i skriptblocket, utan bara skickar det till fjärrdatorn. Tänk till exempel på följande kommando:

Invoke-Command –ScriptBlock { Do-Something –Credential (Get-Credential) } -ComputerName LON-DC1

Det här kommandot kör cmdleten Get-Credential på fjärrdatorn. Om du försöker köra Get-Credential på en lokal dator används en grafisk dialogruta för att fråga efter autentiseringsuppgifterna.

Fråga: Fungerar kommandot när det körs på en fjärrdator? Om du till exempel körde föregående kommando på 100 fjärrdatorer, uppmanas du att ange 100 autentiseringsuppgifter?

Överväg nu den här ändrade versionen av kommandot:

Invoke-Command –ScriptBlock { Param($c) Do-Something –Credential $c }
               -ComputerName LON-DC1
               -ArgumentList (Get-Credential)

Det här kommandot kör Get-Credential på den lokala datorn och kör den bara en gång. Det resulterande objektet skickas till parametern $c för skriptblocket, vilket gör att varje dator kan använda samma autentiseringsuppgifter.

De här exemplen illustrerar vikten av att skriva fjärrkommunikationskommandon noggrant. Genom att använda en kombination av kommandon som körs via fjärranslutning och lokalt kan du uppnå olika användbara mål.

Bevarande

Med hjälp av de tekniker som beskrivs här skapar fjärrdatorn varje gång du använder Invoke-Command en ny wsmprovhost-process och kör kommandot eller kommandona. Sedan returneras resultatet och den Windows PowerShell-instansen stängs. Varje efterföljande Invoke-Command, även om det görs på samma dator, liknar att öppna ett nytt Windows PowerShell-fönster. Allt arbete som utförts av en tidigare session finns inte om du inte sparar det på en disk eller något annat beständigt lagringsutrymme. Tänk till exempel på följande kommando:

Invoke-Command –ComputerName LON-DC1 –ScriptBlock { $x = 'BITS' }
Invoke-Command –ComputerName LON-DC1 –ScriptBlock { Get-Service –Name $x }

I det här exemplet misslyckas Get-Service eftersom den är beroende av värdet för en variabel som skapades som en del av den tidigare wsmprovhost-processen. När det första skriptet som anropas av Invoke-Command har slutförts rensas dess variabler från minnet. För att åtgärda det här problemet kan du skapa en wsmprovhost-process på en fjärrdator så att du kan skicka efterföljande kommandon till den.

Flera datornamn

Parametern –ComputerName i Invoke-Command kan acceptera alla typer av strängobjekt som datornamn. I följande lista beskrivs olika tekniker som kan användas för att skapa sådana samlingar:

  • -ComputerName ONE,TWO,THREE. En statisk, kommaavgränsad lista över datornamn.
  • -ComputerName (Get-Content Names.txt). Läser namn från en textfil med namnet Names.txt, förutsatt att filen innehåller ett datornamn per rad.
  • -ComputerName (Import-Csv Computers.csv | Välj –ExpandProperty Computer). Läser en CSV-fil (kommaavgränsat värde) med namnet Computers.csv och innehåller en kolumn med namnet Dator som innehåller datornamn.
  • -ComputerName (Get-ADComputer –Filter * | Välj –ExpandProperty Name). Kör frågor mot varje datorobjekt i AD DS, vilket kan ta lång tid i en stor domän.

Vanliga misstag vid användning av datornamn

Var försiktig när du anger ett datornamn. Granska till exempel följande kommando:

Invoke-Command –ScriptBlock { Get-Service –ComputerName ONE,TWO }

Det här kommandot tillhandahåller inte parametern –ComputerName till Invoke-Command. Därför körs kommandot på den lokala datorn. Den lokala datorn kommer att köra Get-Service och rikta in sig på datorer med namnen ONE och TWO. Protokollen som används av Get-Service kommer att användas istället för Windows PowerShell-fjärrkommunikation. Jämför detta med följande kommando:

Invoke-Command –ScriptBlock { Get-Service } –ComputerName ONE,TWO

Det här kommandot använder Windows PowerShell-fjärrkommunikation för att ansluta till datorer med namnet ONE och TWO. Var och en av dessa datorer kör Get-Service lokalt, och returnerar sina resultat genom fjärranslutning.

För mer interaktiva Windows PowerShell-fjärrkommunikationssituationer kan du hantera enskilda sessioner som separata entiteter. För att göra detta skapar du först en session med kommandot New-PSSession . Fördelen med att använda kommandot New-PSSession är att sessionen bevaras i flera Invoke-Command-instanser , så att du kan skicka variabler och objekt till andra kommandon i skriptet. Du kan skapa beständiga sessioner med hjälp av kommandot New-PSSession och tilldela dem till en variabel. Sedan kan du referera till variabeln senare med kommandot Invoke-Command . När du är klar kan du stänga beständiga sessioner med kommandot Remove-PSSession .