Capítulo 8 - Comunicação remota do PowerShell
O PowerShell tem muitas maneiras diferentes de executar comandos em computadores remotos. No último capítulo, você viu como consultar remotamente o WMI usando os cmdlets CIM. O PowerShell também inclui vários cmdlets que têm um parâmetro ComputerName interno.
Como mostrado no exemplo a seguir, Get-Command
pode ser usado com o parâmetro ParameterName para determinar quais comandos têm um parâmetro ComputerName .
Get-Command -ParameterName ComputerName
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Add-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Clear-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Connect-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Enter-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Get-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-HotFix 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-WmiObject 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Invoke-Command 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Invoke-WmiMethod 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Limit-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Receive-Job 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Receive-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Register-WmiEvent 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Remove-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Remove-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Remove-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Remove-WmiObject 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Rename-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Restart-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Send-MailMessage 3.1.0.0 Microsoft.PowerShell.Utility
Cmdlet Set-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Set-WmiInstance 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Show-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Test-Connection 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Write-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Comandos como Get-Process
e têm um parâmetro ComputerNameGet-Hotfix
. Esta não é a direção de longo prazo que a Microsoft está seguindo para executar comandos em computadores remotos. Mesmo que você encontre um comando que tenha um parâmetro ComputerName , é provável que você precise especificar credenciais alternativas e ele não tenha um parâmetro Credential . E se você decidiu executar o PowerShell a partir de uma conta elevada, um firewall entre você e o computador remoto pode bloquear a solicitação.
Para usar os comandos de comunicação remota do PowerShell demonstrados neste capítulo, a comunicação remota do PowerShell deve ser habilitada no computador remoto. Use o cmdlet para habilitar a Enable-PSRemoting
comunicação remota do PowerShell.
Enable-PSRemoting
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.
WinRM has been updated for remote management.
WinRM firewall exception enabled.
Comunicação Remota Individual
Se você quiser que sua sessão remota seja interativa, então a comunicação remota individual é o que você quer.
Esse tipo de comunicação remota é fornecido por meio do Enter-PSSession
cmdlet.
No último capítulo, armazenei minhas credenciais de administrador de domínio em uma variável chamada $Cred
. Se você ainda não tiver feito isso, vá em frente e armazene suas credenciais de administrador de $Cred
domínio na variável.
Isso permite que você insira as credenciais uma vez e use-as por comando, desde que sua sessão atual do PowerShell esteja ativa.
$Cred = Get-Credential
Crie uma sessão de comunicação remota do PowerShell um-para-um para o controlador de domínio chamado dc01.
Enter-PSSession -ComputerName dc01 -Credential $Cred
[dc01]: PS C:\Users\Administrator\Documents>
Observe que, no exemplo anterior, o prompt do PowerShell é precedido por [dc01]
. Isso significa que você está em uma sessão interativa do PowerShell para o computador remoto chamado dc01. Todos os comandos executados são executados em dc01, não no computador local. Além disso, lembre-se de que você só tem acesso aos comandos do PowerShell existentes no computador remoto e não aos do computador local. Em outras palavras, se você instalou módulos adicionais no seu computador, eles não estão acessíveis no computador remoto.
Quando você está conectado a um computador remoto por meio de uma sessão de comunicação remota interativa do PowerShell um-para-um, você está efetivamente sentado no computador remoto. Os objetos são objetos normais, assim como aqueles com os quais você tem trabalhado ao longo de todo este livro.
[dc01]: Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize64
PM AliasProperty PM = PagedMemorySize64
SI AliasProperty SI = SessionId
VM AliasProperty VM = VirtualMemorySize64
WS AliasProperty WS = WorkingSet64
Disposed Event System.EventHandler Disposed(System.Object, ...
ErrorDataReceived Event System.Diagnostics.DataReceivedEventHandler ...
Exited Event System.EventHandler Exited(System.Object, Sy...
OutputDataReceived Event System.Diagnostics.DataReceivedEventHandler ...
BeginErrorReadLine Method void BeginErrorReadLine()
BeginOutputReadLine Method void BeginOutputReadLine()
CancelErrorRead Method void CancelErrorRead()
CancelOutputRead Method void CancelOutputRead()
Close Method void Close()
CloseMainWindow Method bool CloseMainWindow()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(...
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Kill Method void Kill()
Refresh Method void Refresh()
Start Method bool Start()
ToString Method string ToString()
WaitForExit Method bool WaitForExit(int milliseconds), void Wai...
WaitForInputIdle Method bool WaitForInputIdle(int milliseconds), boo...
__NounName NoteProperty string __NounName=Process
BasePriority Property int BasePriority {get;}
Container Property System.ComponentModel.IContainer Container {...
EnableRaisingEvents Property bool EnableRaisingEvents {get;set;}
ExitCode Property int ExitCode {get;}
ExitTime Property datetime ExitTime {get;}
Handle Property System.IntPtr Handle {get;}
HandleCount Property int HandleCount {get;}
HasExited Property bool HasExited {get;}
Id Property int Id {get;}
MachineName Property string MachineName {get;}
MainModule Property System.Diagnostics.ProcessModule MainModule ...
MainWindowHandle Property System.IntPtr MainWindowHandle {get;}
MainWindowTitle Property string MainWindowTitle {get;}
MaxWorkingSet Property System.IntPtr MaxWorkingSet {get;set;}
MinWorkingSet Property System.IntPtr MinWorkingSet {get;set;}
Modules Property System.Diagnostics.ProcessModuleCollection M...
NonpagedSystemMemorySize Property int NonpagedSystemMemorySize {get;}
NonpagedSystemMemorySize64 Property long NonpagedSystemMemorySize64 {get;}
PagedMemorySize Property int PagedMemorySize {get;}
PagedMemorySize64 Property long PagedMemorySize64 {get;}
PagedSystemMemorySize Property int PagedSystemMemorySize {get;}
PagedSystemMemorySize64 Property long PagedSystemMemorySize64 {get;}
PeakPagedMemorySize Property int PeakPagedMemorySize {get;}
PeakPagedMemorySize64 Property long PeakPagedMemorySize64 {get;}
PeakVirtualMemorySize Property int PeakVirtualMemorySize {get;}
PeakVirtualMemorySize64 Property long PeakVirtualMemorySize64 {get;}
PeakWorkingSet Property int PeakWorkingSet {get;}
PeakWorkingSet64 Property long PeakWorkingSet64 {get;}
PriorityBoostEnabled Property bool PriorityBoostEnabled {get;set;}
PriorityClass Property System.Diagnostics.ProcessPriorityClass Prio...
PrivateMemorySize Property int PrivateMemorySize {get;}
PrivateMemorySize64 Property long PrivateMemorySize64 {get;}
PrivilegedProcessorTime Property timespan PrivilegedProcessorTime {get;}
ProcessName Property string ProcessName {get;}
ProcessorAffinity Property System.IntPtr ProcessorAffinity {get;set;}
Responding Property bool Responding {get;}
SafeHandle Property Microsoft.Win32.SafeHandles.SafeProcessHandl...
SessionId Property int SessionId {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
StandardError Property System.IO.StreamReader StandardError {get;}
StandardInput Property System.IO.StreamWriter StandardInput {get;}
StandardOutput Property System.IO.StreamReader StandardOutput {get;}
StartInfo Property System.Diagnostics.ProcessStartInfo StartInf...
StartTime Property datetime StartTime {get;}
SynchronizingObject Property System.ComponentModel.ISynchronizeInvoke Syn...
Threads Property System.Diagnostics.ProcessThreadCollection T...
TotalProcessorTime Property timespan TotalProcessorTime {get;}
UserProcessorTime Property timespan UserProcessorTime {get;}
VirtualMemorySize Property int VirtualMemorySize {get;}
VirtualMemorySize64 Property long VirtualMemorySize64 {get;}
WorkingSet Property int WorkingSet {get;}
WorkingSet64 Property long WorkingSet64 {get;}
PSConfiguration PropertySet PSConfiguration {Name, Id, PriorityClass, Fi...
PSResources PropertySet PSResources {Name, Id, Handlecount, WorkingS...
Company ScriptProperty System.Object Company {get=$this.Mainmodule....
CPU ScriptProperty System.Object CPU {get=$this.TotalProcessorT...
Description ScriptProperty System.Object Description {get=$this.Mainmod...
FileVersion ScriptProperty System.Object FileVersion {get=$this.Mainmod...
Path ScriptProperty System.Object Path {get=$this.Mainmodule.Fil...
Product ScriptProperty System.Object Product {get=$this.Mainmodule....
ProductVersion ScriptProperty System.Object ProductVersion {get=$this.Main...
[dc01]:
Quando terminar de trabalhar com o computador remoto, saia da sessão de comunicação remota um-para-um usando o Exit-PSSession
cmdlet.
[dc01]: Exit-PSSession
Comunicação remota um-para-muitos
Às vezes, você pode precisar executar uma tarefa interativamente em um computador remoto. Mas a comunicação remota é muito mais poderosa ao executar uma tarefa em vários computadores remotos ao mesmo tempo. Use o Invoke-Command
cmdlet para executar um comando em um ou mais computadores remotos ao mesmo tempo.
Invoke-Command -ComputerName dc01, sql02, web01 {Get-Service -Name W32time} -Credential $Cred
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Running W32time Windows Time web01
Start... W32time Windows Time dc01
Running W32time Windows Time sql02
No exemplo anterior, três servidores foram consultados quanto ao status do serviço de Tempo do Windows. O Get-Service
cmdlet foi colocado dentro do bloco de script do Invoke-Command
. Get-Service
na verdade, é executado no computador remoto e os resultados são retornados ao computador local como objetos desserializados.
Canalizar o comando anterior para Get-Member
mostrar que os resultados são realmente objetos desserializados.
Invoke-Command -ComputerName dc01, sql02, web01 {Get-Service -Name W32time} -Credential $Cred | Get-Member
TypeName: Deserialized.System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
GetType Method type GetType()
ToString Method string ToString(), string ToString(string format, Sys...
Name NoteProperty string Name=W32time
PSComputerName NoteProperty string PSComputerName=sql02
PSShowComputerName NoteProperty bool PSShowComputerName=True
RequiredServices NoteProperty Deserialized.System.ServiceProcess.ServiceController[...
RunspaceId NoteProperty guid RunspaceId=570313c4-ac84-4109-bf67-c6b33236af0a
CanPauseAndContinue Property System.Boolean {get;set;}
CanShutdown Property System.Boolean {get;set;}
CanStop Property System.Boolean {get;set;}
Container Property {get;set;}
DependentServices Property Deserialized.System.ServiceProcess.ServiceController[...
DisplayName Property System.String {get;set;}
MachineName Property System.String {get;set;}
ServiceHandle Property System.String {get;set;}
ServiceName Property System.String {get;set;}
ServicesDependedOn Property Deserialized.System.ServiceProcess.ServiceController[...
ServiceType Property System.String {get;set;}
Site Property {get;set;}
StartType Property System.String {get;set;}
Status Property System.String {get;set;}
Observe que a maioria dos métodos está faltando em objetos desserializados. Isto significa que não são objetos vivos; eles são inertes. Não é possível iniciar ou parar um serviço usando um objeto desserializado porque é um instantâneo do estado desse objeto, o ponto em que o comando foi executado no computador remoto.
Isso não significa que você não possa iniciar ou parar um serviço usando um método com Invoke-Command
. Isso significa apenas que o método tem que ser chamado na sessão remota.
Vou parar o serviço de Tempo do Windows em todos esses três servidores remotos usando o método Stop() para provar esse ponto.
Invoke-Command -ComputerName dc01, sql02, web01 {(Get-Service -Name W32time).Stop()} -Credential $Cred
Invoke-Command -ComputerName dc01, sql02, web01 {Get-Service -Name W32time} -Credential $Cred
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Stopped W32time Windows Time web01
Stopped W32time Windows Time dc01
Stopped W32time Windows Time sql02
Como mencionado em um capítulo anterior, se existir um cmdlet para realizar uma tarefa, recomendo usá-lo em vez de usar um método. No cenário anterior, recomendo usar o Stop-Service
cmdlet em vez do método stop. Optei por usar o método Stop() para provar um ponto, já que muitas pessoas estão sob o equívoco de que os métodos não podem ser chamados ao usar a comunicação remota do PowerShell. Eles não podem ser chamados no objeto retornado porque ele é desserializado, mas podem ser chamados na própria sessão remota.
Sessões do PowerShell
No último exemplo da seção anterior, executei dois comandos usando o Invoke-Command
cmdlet.
Isso significa que duas sessões separadas tiveram que ser configuradas e derrubadas para executar esses dois comandos.
Semelhante às sessões CIM discutidas no Capítulo 7, uma sessão do PowerShell para um computador remoto pode ser usada para executar vários comandos no computador remoto sem a sobrecarga de uma nova sessão para cada comando individual.
Crie uma sessão do PowerShell para cada um dos três computadores com os quais trabalhamos neste capítulo, DC01, SQL02 e WEB01.
$Session = New-PSSession -ComputerName dc01, sql02, web01 -Credential $Cred
Agora use a variável nomeada $Session
para iniciar o serviço de Tempo do Windows usando um método e verifique o status do serviço.
Invoke-Command -Session $Session {(Get-Service -Name W32time).Start()}
Invoke-Command -Session $Session {Get-Service -Name W32time}
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Running W32time Windows Time web01
Start... W32time Windows Time dc01
Running W32time Windows Time sql02
Depois que a sessão é criada usando credenciais alternativas, não é mais necessário especificar as credenciais cada vez que um comando é executado.
Quando terminar de usar as sessões, certifique-se de removê-las.
Get-PSSession | Remove-PSSession
Resumo
Neste capítulo, você aprendeu sobre a comunicação remota do PowerShell, como executar comandos em uma sessão interativa com um computador remoto e como executar comandos em vários computadores usando a comunicação remota um-para-muitos. Você também aprendeu os benefícios de usar uma sessão do PowerShell ao executar vários comandos no mesmo computador remoto.
Rever
- Como habilitar a comunicação remota do PowerShell?
- O que é o comando do PowerShell para iniciar uma sessão interativa com um computador remoto?
- Qual é a vantagem de usar uma sessão remota do PowerShell em vez de apenas especificar o nome do computador com cada comando?
- Uma sessão remota do PowerShell pode ser usada com uma sessão de comunicação remota individual?
- Qual é a diferença no tipo de objetos retornados por cmdlets em relação aos retornados ao executar esses mesmos cmdlets em computadores remotos com
Invoke-Command
?