第 8 章 - PowerShell 远程处理
PowerShell 提供多种不同的方法对远程计算机运行命令。 在上一章中,你已了解如何使用 CIM cmdlet 远程查询 WMI。 PowerShell 还包括多个具有内置 ComputerName 参数的 cmdlet。
如下面的示例中所示,可以配合使用 Get-Command
和 ParameterName 参数,以确定哪些命令具有 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
Get-Process
和 Get-Hotfix
之类的命令具有 ComputerName 参数。 这并非 Microsoft 针对远程计算机运行命令的长期方向。 即使你找到的命令具有 ComputerName 参数,也可能需要指定备用凭据,并且它没有 Credential 参数。 如果决定从提升的帐户运行 PowerShell,则你与远程计算机之间的防火墙可能会阻止请求。
要使用本章中演示的 PowerShell 远程处理命令,必须在远程计算机上启用 PowerShell 远程处理。 使用 Enable-PSRemoting
cmdlet 启用 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.
一对一远程处理
如果要使远程会话成为交互式会话,则需要一对一远程处理。
这种类型的远程处理是通过 Enter-PSSession
cmdlet 提供的。
在上一章中,我将我的域管理员凭据存储在名为 $Cred
的变量中。 如果尚未执行此操作,请继续将域管理员凭据存储在 $Cred
变量中。
这允许输入一次凭据,并在当前 PowerShell 会话处于活动状态时,按命令使用这些凭据。
$Cred = Get-Credential
创建与名为 dc01 的域控制器的一对一 PowerShell 远程处理会话。
Enter-PSSession -ComputerName dc01 -Credential $Cred
[dc01]: PS C:\Users\Administrator\Documents>
请注意,在上一个示例中,PowerShell 提示符的前缀是 [dc01]
。 这意味着你处于与名为 dc01 的远程计算机的交互式 PowerShell 会话中。 在 dc01 上而不是在本地计算机上执行的任何命令。 另外,请记住,你只能访问远程计算机上存在的 PowerShell 命令,而不是本地计算机上的 PowerShell 命令。 换句话说,如果你已在计算机上安装了其他模块,则无法在远程计算机上访问它们。
通过一对一交互式 PowerShell 远程处理会话连接到远程计算机时,实际上就是在使用远程计算机。 相关对象是普通对象,就像你在整本书中使用的对象一样。
[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]:
使用完远程计算机后,请使用 Exit-PSSession
cmdlet 退出一对一远程处理会话。
[dc01]: Exit-PSSession
一对多远程处理
有时,你可能需要在远程计算机上以交互方式执行任务。 但在多台远程计算机上同时执行一项任务时,远程处理功能要强大得多。 使用 Invoke-Command
cmdlet 对一台或多台远程计算机同时运行命令。
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
在上面的示例中,查询了三台服务器的 Windows 时间服务状态。 Get-Service
cmdlet 位于 Invoke-Command
的脚本块内。 Get-Service
实际上在远程计算机上运行,而结果作为反序列化的对象返回到本地计算机。
通过将上一条命令通过管道传递到 Get-Member
,可表明结果确实是反序列化的对象。
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;}
请注意,反序列化的对象上缺少大多数方法。 这意味着它们不是活动对象;而是静态对象。 无法使用反序列化的对象启动或停止服务,因为它是命令在远程计算机上运行时,该对象所处状态的快照。
但这并不意味着无法使用带有 Invoke-Command
的方法来启动或停止服务。 这只意味着必须在远程会话中调用该方法。
我将使用 Stop() 方法停止全部三台远程服务器上的 Windows 时间服务,以证明这一点。
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
如前一章中所述,如果存在用于完成任务的 cmdlet,则建议使用它,而不是使用方法。 在前面的情况中,建议使用 Stop-Service
cmdlet,而不是停止方法。 我选择使用 Stop() 方法来证明这一点,因为很多人都误认为在使用 PowerShell 远程处理时不能调用方法。 无法在返回的对象上调用方法(因为返回的是反序列化的对象),但可以在远程会话本身之中调用它们。
PowerShell 会话
在上一节的最后一个示例中,我使用 Invoke-Command
cmdlet 运行了两个命令。
这意味着必须设置两个单独的会话,并进行拆解以运行这两个命令。
与第 7 章中讨论的 CIM 会话类似,可以使用与远程计算机的 PowerShell 会话对远程计算机运行多个命令,而不会产生每个单独命令的新会话开销。
为本章中使用的三台计算机 DC01、SQL02 和 WEB01 分别创建一个 PowerShell 会话。
$Session = New-PSSession -ComputerName dc01, sql02, web01 -Credential $Cred
现在,使用名为 $Session
的变量通过某个方法启动 Windows 时间服务,并检查服务的状态。
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
使用备用凭据创建会话后,每次运行命令时,都不再需要指定凭据。
使用完会话后,请确保将其删除。
Get-PSSession | Remove-PSSession
总结
在本章中,你已了解 PowerShell 远程处理、如何在与一台远程计算机的交互式会话中运行命令,以及如何使用一对多远程处理对多台计算机运行命令。 你还了解了对同一台远程计算机运行多个命令时,使用 PowerShell 会话的好处。
审阅
- 如何启用 PowerShell 远程处理?
- 用于启动与远程计算机的交互式会话的 PowerShell 命令是什么?
- 与仅使用每个命令指定计算机名相比,使用 PowerShell 远程处理会话有何优势?
- PowerShell 远程处理会话是否可以与一对一远程处理会话一起使用?
- Cmdlet 返回的对象类型与使用
Invoke-Command
对远程计算机运行相同 cmdlet 时返回的对象类型有什么不同?