Usare la comunicazione remota uno-a-molti con Windows PowerShell

Completato

La comunicazione remota uno-a-molti consente di inviare un singolo comando a più computer in parallelo. Ogni computer eseguirà il comando trasmesso, serializzerà i risultati in formato XML e ritrasmetterà tali risultati al computer. Il computer quindi deserializza il codice XML in oggetti e li inserisce nella pipeline di Windows PowerShell. Quando si esegue questa operazione, vengono aggiunte diverse proprietà a ogni oggetto, tra cui una proprietà PSComputerName che indica il computer da cui proviene ogni risultato. Questa proprietà consente di ordinare, raggruppare e filtrare in base al nome computer.

È possibile usare la comunicazione remota uno-a-molti con due tecniche diverse:

  • Invoke-Command –ComputerName name1,name2 –ScriptBlock { comando }. Questa tecnica invia il comando (o i comandi) contenuto nel blocco di script ai computer elencati. Questa tecnica è utile per l'invio di uno o due comandi. Più comandi vengono separati da punto e virgola.
  • Invoke-Command –ComputerName name1,name2 –FilePath filepath. Questa tecnica invia i contenuti di un file di script con estensione ps1 ai computer elencati. Il computer locale apre il file e legge il relativo contenuto. Tuttavia, i computer remoti non devono avere accesso diretto al file. Questa tecnica è utile per l'invio di un file di comandi di grandi dimensioni, ad esempio uno script completo.

Nota

All'interno di qualsiasi blocco di script (incluso il blocco di script fornito al parametro –ScriptBlock) è possibile usare un punto e virgola per separare più comandi. Ad esempio, { Get-Service ; Get-Process } eseguirà Get-Service e quindi Get-Process.

Limitazione

Per gestire le risorse nel computer locale, PowerShell include una funzionalità di limitazione per comando che consente di limitare il numero di connessioni remote simultanee stabilite per ogni comando. Per impostazione predefinita, Windows PowerShell si connetterà solo a 32 computer contemporaneamente. Se si elencano più di 32 computer, le connessioni agli altri computer verranno accodate. Una volta terminate le sessioni ad alcuni computer dal primo batch e restituiti i relativi risultati, verranno avviate le connessioni ai computer nel batch successivo.

È possibile modificare questo comportamento usando il parametro –ThrottleLimit di Invoke-Command. L'aumento del numero non inserisce un carico aggiuntivo nei computer remoti. Tuttavia, inserisce un carico aggiuntivo nel computer in cui è stato richiamato Invoke-Command. Viene usata anche una larghezza di banda maggiore. Ogni connessione simultanea è fondamentalmente un thread di Windows PowerShell. Pertanto, l'aumento del numero di computer comporta un maggiore utilizzo di memoria e velocità del processore nel computer locale.

Passaggio di valori

I contenuti del blocco di script o del file vengono trasmessi come testo letterale ai computer remoti che li eseguono esattamente come sono. Il computer non analizza il blocco di script o il file in cui è stato eseguito il comando Invoke-Command. Osservare l'esempio di comando seguente:

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

In questo scenario, la variabile $var viene impostata nel computer locale anziché essere inclusa nel blocco di script da eseguire in LON-DC1. In altre parole, $var non è definito o impostato nella sessione di comunicazione remota di PowerShell su LON-DC1. Si tratta di un errore comune per gli amministratori che non hanno familiarità con Windows PowerShell.

Esecuzione di comandi in locale e in remoto

Prestare attenzione ai comandi racchiusi nel blocco di script, che verranno passati al computer remoto. Tenere presente che il computer locale non elabora alcun contenuto del blocco di script, ma semplicemente lo passa al computer remoto. Si consideri, ad esempio, il comando seguente:

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

Questo comando eseguirà il cmdlet Get-Credential nel computer remoto. Se si prova a eseguire Get-Credential in un computer locale, verrà usata una finestra di dialogo grafica per richiedere le credenziali.

Domanda: Questo comando funzionerà quando viene eseguito in un computer remoto? Ad esempio, se il comando precedente è stato eseguito su 100 computer remoti, verranno richieste 100 credenziali?

Prendere ora in considerazione questa versione modificata del comando:

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

Questo comando esegue Get-Credential nel computer locale e lo esegue una sola volta. L'oggetto risultante viene passato al parametro $c del blocco di script, consentendo a ogni computer di usare le stesse credenziali.

Questi esempi illustrano attentamente l'importanza della scrittura di comandi in modalità remota. Usando una combinazione di comandi in modalità remota e locale, è possibile raggiungere vari obiettivi utili.

Persistenza

Usando le tecniche descritte qui, ogni volta che si usa Invoke-Command, il computer remoto crea un nuovo processo wsmprovhost ed esegue il comando o i comandi. Restituisce quindi i risultati e chiude l'istanza di Windows PowerShell. Ogni comando Invoke-Command successivo, anche se eseguito nello stesso computer, è simile all'apertura di una nuova finestra di Windows PowerShell. Qualsiasi attività svolta da una sessione precedente non esiste a meno che non venga salvata in un disco o in un'altra risorsa di archiviazione persistente. Si consideri, ad esempio, il comando seguente:

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

In questo esempio, il comando Get-Service avrà esito negativo, perché dipende dal valore di una variabile creata come parte del processo wsmprovhost precedente. Quando il primo script richiamato da Invoke-Command viene completato, le relative variabili vengono cancellate dalla memoria. Per risolvere questo problema, è possibile creare un processo wsmprovhost in un computer remoto in modo che sia possibile inviare correttamente comandi successivi.

Nomi computer multipli

Il parametro –ComputerName di Invoke-Command può accettare qualsiasi raccolta di oggetti stringa come nomi computer. L'elenco seguente descrive diverse tecniche che possono essere usate per creare tali raccolte:

  • -ComputerName ONE,TWO,THREE. Un elenco statico di nomi computer delimitati da virgole.
  • -ComputerName (Get-Content Names.txt). Legge i nomi da un file di testo denominato Names.txt, presupponendo che il file contenga un nome computer per riga.
  • -ComputerName (Import-Csv Computers.csv | Select –ExpandProperty Computer). Legge un file con valori delimitati da virgole (CSV) denominato Computers.csv e contiene una colonna denominata Computer contenente nomi computer.
  • -ComputerName (Get-ADComputer –Filter * | Select –ExpandProperty Name). Esegue query su ogni oggetto computer in Active Directory Domain Services, che può richiedere un periodo di tempo significativo in un dominio di grandi dimensioni.

Errori comuni quando si usano i nomi computer

Prestare attenzione alla posizione in cui si specifica un nome computer. Ad esempio, esaminare il comando seguente:

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

Questo comando non fornisce un parametro –ComputerName a Invoke-Command. Questo comando viene quindi eseguito nel computer locale. Il computer locale eseguirà Get-Service destinato a computer denominati ONE e TWO. Verranno usati i protocolli usati da Get-Service anziché la comunicazione remota di Windows PowerShell. Confrontarlo con il comando seguente:

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

Questo comando userà la comunicazione remota di Windows PowerShell per connettersi ai computer denominati ONE e TWO. Ognuno di questi computer eseguirà Get-Service in locale, restituendo i relativi risultati usando la comunicazione remota.

Per situazioni di comunicazione remota di Windows PowerShell più interattive, è possibile gestire singole sessioni come entità separate. A tale scopo, creare prima una sessione usando il comando New-PSSession. Il vantaggio dell'uso del comando New-PSSession è che la sessione persiste in più istanze di Invoke-Command, consentendo di passare variabili e oggetti ad altri comandi nello script. È possibile creare sessioni persistenti usando il comando New-PSSession e assegnandolo a una variabile. È quindi possibile fare riferimento alla variabile in un secondo momento usando il comando Invoke-Command. Al termine, è possibile chiudere sessioni persistenti usando il comando Remove-PSSession.