Usar a comunicação remota de um para muitos por meio do Windows PowerShell
A comunicação remota de um para muitos permite que você envie um único comando para vários computadores paralelamente. Cada computador executará o comando que você transmitir, serializará os resultados em XML e transmitirá esses resultados novamente para o computador. Em seguida, o computador desserializará o XML nos objetos e os colocará no pipeline do Windows PowerShell. Ao fazer isso, várias propriedades são adicionadas a cada objeto, incluindo a propriedade PSComputerName que indica de qual computador veio cada resultado. Essa propriedade permite que você classifique, agrupe e filtre de acordo com o nome do computador.
Você pode usar a comunicação remota de um para muitos, aplicando duas técnicas diferentes:
- Invoke-Command –ComputerName name1,name2 –ScriptBlock { command }. Essa técnica envia o comando (ou comandos) contido no bloco de script para os computadores listados. Ela é útil para enviar um ou dois comandos. Vários comandos são separados por um ponto e vírgula.
- Invoke-Command –ComputerName name1,name2 –FilePath filepath. Essa técnica envia o conteúdo de um arquivo de script com uma extensão de nome de arquivo .ps1 para os computadores listados. O computador local abre o arquivo e lê o conteúdo. No entanto, os computadores remotos não precisam ter acesso direto ao arquivo. Essa técnica é útil para enviar um grande arquivo de comandos, como um script completo.
Observação
Em blocos de script (incluindo o bloco de script fornecido para o parâmetro –ScriptBlock), você pode usar um ponto e vírgula para separar vários comandos. Por exemplo, { Get-Service ; Get-Process }
executará o Get-Service e, em seguida, o Get-Process.
Limitação
Para ajudar a gerenciar os recursos no computador local, o PowerShell inclui um recurso de limitação por comando, que permite limitar o número de conexões remotas simultâneas estabelecidas para cada comando. Por padrão, o Windows PowerShell será conectado a apenas 32 computadores ao mesmo tempo. Se você listar mais de 32 computadores, as conexões com os outros computadores serão enfileiradas. Depois que as sessões para alguns dos computadores do primeiro lote forem concluídas e retornarem os resultados, as conexões com os computadores no próximo lote serão iniciadas.
Você pode alterar esse comportamento usando o parâmetro –ThrottleLimit do Invoke-Command. Aumentar o número não coloca uma carga adicional nos computadores remotos. No entanto, coloca uma carga adicional no computador em que o Invoke-Command foi invocado. Isso também utiliza mais largura de banda. Cada conexão simultânea é basicamente um thread do Windows PowerShell. Portanto, aumentar o número de computadores consome memória e velocidade do processador no computador local.
Como passar os valores
O conteúdo do bloco de script ou do arquivo é transmitido como texto literal para os computadores remotos, que o executa exatamente como está. O computador não analisa o bloco de script ou o arquivo em que o Invoke-Command foi executado. Considere o seguinte exemplo de comando:
$var = 'BITS'
Invoke-Command –ScriptBlock { Get-Service –Name $var } –Computer LON-DC1
Nesse cenário, a variável $var
está sendo definida no computador local, em vez de ser incluída no bloco de script a ser executado no LON-DC1. Em outras palavras, $var
não é definido ou configurado na sessão de comunicação remota do PowerShell como LON-DC1, o que é um erro comum que os novos administradores do Windows PowerShell geralmente cometem.
Execução local e remota de comandos
Preste muita atenção aos comandos que você coloca no bloco de script, que serão passados para o computador remoto. Lembre-se de que o computador local não processará o conteúdo de bloco de script, mas simplesmente o passará para o computador remoto. Por exemplo, considere o seguinte comando:
Invoke-Command –ScriptBlock { Do-Something –Credential (Get-Credential) } -ComputerName LON-DC1
Esse comando executará o cmdlet Get-Credential no computador remoto. Se você tentar executar o Get-Credential em um computador local, ele usará uma caixa de diálogo gráfica para solicitar a credencial.
Pergunta: esse comando funcionará quando executado em um computador remoto? Por exemplo, se você executou o comando anterior em 100 computadores remotos, você será solicitado a fornecer 100 credenciais?
Agora considere essa versão modificada do comando:
Invoke-Command –ScriptBlock { Param($c) Do-Something –Credential $c }
-ComputerName LON-DC1
-ArgumentList (Get-Credential)
Esse comando executa o Get-Credential no computador local e o faz apenas uma vez. O objeto resultante é passado para o parâmetro $c
do bloco de script, permitindo que cada computador use a mesma credencial.
Esses exemplos ilustram a importância de gravar os comandos de comunicação remota com cuidado. Ao usar uma combinação de comandos de execução remota e local, você pode atingir várias metas úteis.
Persistência
Ao aplicar as técnicas descritas aqui, sempre que você usa o Invoke-Command, o computador remoto cria um novo processo wsmprovhost e executa o comando ou os comandos. Em seguida, retorna os resultados e fecha essa instância do Windows PowerShell. Cada Invoke-Command sucessivo, mesmo que executado no mesmo computador, é semelhante a abrir uma nova janela do Windows PowerShell. Qualquer trabalho feito por uma sessão anterior não existirá, a menos que você o salve em um disco ou em algum outro armazenamento persistente. Por exemplo, considere o seguinte comando:
Invoke-Command –ComputerName LON-DC1 –ScriptBlock { $x = 'BITS' }
Invoke-Command –ComputerName LON-DC1 –ScriptBlock { Get-Service –Name $x }
Neste exemplo, o Get-Service falharia, pois depende do valor de uma variável criada como parte do processo wsmprovhost anterior. Quando o primeiro script invocado pelo Invoke-Command for concluído, as variáveis serão apagadas da memória. Para resolver esse problema, você pode criar um processo wsmprovhost em um computador remoto para que você possa enviar com êxito comandos sucessivos a ele.
Vários nomes do computador
O parâmetro –ComputerName do Invoke-Command pode aceitar qualquer coleção de objetos de cadeia de caracteres como nomes do computador. A lista a seguir descreve diferentes técnicas que podem ser usadas para criar essas coleções:
- -ComputerName ONE,TWO,THREE. Uma lista estática, separada por vírgulas, de nomes do computador.
- -ComputerName (Get-Content Names.txt). Lê os nomes de um arquivo de texto chamado Names.txt, supondo que o arquivo contenha um nome do computador por linha.
- -ComputerName (Import-Csv Computers.csv | Select –ExpandProperty Computer). Lê um arquivo CSV (valor separado por vírgula) chamado Computers.csv e contém uma coluna chamada Computador, que contém os nomes do computador.
- -ComputerName (Get-ADComputer –Filter * | Select –ExpandProperty Name). Consulta todos os objetos de computador no AD DS, o que pode demorar consideravelmente em um domínio grande.
Erros comuns ao usar os nomes do computador
Tenha cuidado ao especificar um nome do computador. Por exemplo, examine o seguinte comando:
Invoke-Command –ScriptBlock { Get-Service –ComputerName ONE,TWO }
Este comando não fornece o parâmetro –ComputerName para o Invoke-Command. Portanto, o comando é executado no computador local. O computador local executará o Get-Service visando os computadores chamados ONE e TWO. Os protocolos usados pelo Get-Service serão seguidos, em vez da comunicação remota do Windows PowerShell. Compare isso ao comando a seguir:
Invoke-Command –ScriptBlock { Get-Service } –ComputerName ONE,TWO
Esse comando usará a comunicação remota do Windows PowerShell para se conectar ao computadores chamados ONE e TWO. Cada um desses computadores executará o Get-Service localmente, retornando os resultados que usam a comunicação remota.
Para ver mais situações interativas de comunicação remota do Windows PowerShell, você pode gerenciar as sessões individuais como entidades separadas. Para fazer isso, primeiro crie uma sessão usando o comando New-PSSession. O benefício de usar o comando New-PSSession é que a sessão persistirá em várias instâncias do Invoke-Command, permitindo que você passe variáveis e objetos para outros comandos no script. Você pode criar sessões persistentes usando o comando New-PSSession e atribuindo-o a uma variável. Você pode referenciar a variável mais tarde usando o comando Invoke-Command. Quando terminar, você pode fechar as sessões persistentes usando o comando Remove-PSSession.