PowerShell 提供了多种针对远程计算机运行命令的方法。 上一章介绍了如何使用 CIM cmdlet 远程查询 WMI。 PowerShell 还包括一些具有内置 ComputerName 参数的 cmdlet。
如以下示例所示,可以使用 Get-Command
ParameterName 参数来标识包含 ComputerName 参数的 cmdlet。
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 来启用它。
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
。 只要当前 PowerShell 会话保持活动状态,此方法允许你输入凭据一次,并按命令重复使用它们。
$Cred = Get-Credential
与名为 dc01 的域控制器建立一对一 PowerShell 远程处理会话。
Enter-PSSession -ComputerName dc01 -Credential $Cred
请注意,PowerShell 提示符前面有 [dc01]
。 此前缀指示你正在与名为 dc01 的远程计算机进行交互式会话。 现在运行的任何命令在 dc01 上执行,而不是本地计算机。
[dc01]: PS C:\Users\Administrator\Documents>
请记住,只能访问远程计算机上安装的 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(Sy...
ErrorDataReceived Event System.Diagnostics.DataReceived...
Exited Event System.EventHandler Exited(Syst...
OutputDataReceived Event System.Diagnostics.DataReceived...
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 ...
Dispose Method void Dispose(), void IDisposabl...
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetim...
Kill Method void Kill()
Refresh Method void Refresh()
Start Method bool Start()
ToString Method string ToString()
WaitForExit Method bool WaitForExit(int millisecon...
WaitForInputIdle Method bool WaitForInputIdle(int milli...
__NounName NoteProperty string __NounName=Process
BasePriority Property int BasePriority {get;}
Container Property System.ComponentModel.IContaine...
EnableRaisingEvents Property bool EnableRaisingEvents {get;s...
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.ProcessModul...
MainWindowHandle Property System.IntPtr MainWindowHandle ...
MainWindowTitle Property string MainWindowTitle {get;}
MaxWorkingSet Property System.IntPtr MaxWorkingSet {ge...
MinWorkingSet Property System.IntPtr MinWorkingSet {ge...
Modules Property System.Diagnostics.ProcessModul...
NonpagedSystemMemorySize Property int NonpagedSystemMemorySize {g...
NonpagedSystemMemorySize64 Property long NonpagedSystemMemorySize64...
PagedMemorySize Property int PagedMemorySize {get;}
PagedMemorySize64 Property long PagedMemorySize64 {get;}
PagedSystemMemorySize Property int PagedSystemMemorySize {get;}
PagedSystemMemorySize64 Property long PagedSystemMemorySize64 {g...
PeakPagedMemorySize Property int PeakPagedMemorySize {get;}
PeakPagedMemorySize64 Property long PeakPagedMemorySize64 {get;}
PeakVirtualMemorySize Property int PeakVirtualMemorySize {get;}
PeakVirtualMemorySize64 Property long PeakVirtualMemorySize64 {g...
PeakWorkingSet Property int PeakWorkingSet {get;}
PeakWorkingSet64 Property long PeakWorkingSet64 {get;}
PriorityBoostEnabled Property bool PriorityBoostEnabled {get;...
PriorityClass Property System.Diagnostics.ProcessPrior...
PrivateMemorySize Property int PrivateMemorySize {get;}
PrivateMemorySize64 Property long PrivateMemorySize64 {get;}
PrivilegedProcessorTime Property timespan PrivilegedProcessorTim...
ProcessName Property string ProcessName {get;}
ProcessorAffinity Property System.IntPtr ProcessorAffinity...
Responding Property bool Responding {get;}
SafeHandle Property Microsoft.Win32.SafeHandles.Saf...
SessionId Property int SessionId {get;}
Site Property System.ComponentModel.ISite Sit...
StandardError Property System.IO.StreamReader Standard...
StandardInput Property System.IO.StreamWriter Standard...
StandardOutput Property System.IO.StreamReader Standard...
StartInfo Property System.Diagnostics.ProcessStart...
StartTime Property datetime StartTime {get;}
SynchronizingObject Property System.ComponentModel.ISynchron...
Threads Property System.Diagnostics.ProcessThrea...
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, Prio...
PSResources PropertySet PSResources {Name, Id, Handleco...
Company ScriptProperty System.Object Company {get=$thi...
CPU ScriptProperty System.Object CPU {get=$this.To...
Description ScriptProperty System.Object Description {get=...
FileVersion ScriptProperty System.Object FileVersion {get=...
Path ScriptProperty System.Object Path {get=$this.M...
Product ScriptProperty System.Object Product {get=$thi...
ProductVersion ScriptProperty System.Object ProductVersion {g...
使用完远程计算机后,运行 Exit-PSSession
cmdlet 以结束远程会话。
[dc01]: Exit-PSSession
一对多远程处理
虽然有时可能需要在远程计算机上以交互方式执行任务,但当你同时跨多个远程系统执行命令时,PowerShell 远程处理会变得更加强大。 使用 Invoke-Command
cmdlet 来同时在一个或多个远程计算机上运行命令。
在以下示例中,你将查询三个服务器以获取 Windows 时间服务的状态。 该 Get-Service
cmdlet 放置在脚本块 Invoke-Command
内,这意味着它在每台远程计算机上执行。
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
要确认返回的对象已反序列化,请将输出通过管道传递给 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(strin...
Name NoteProperty string Name=W32time
PSComputerName NoteProperty string PSComputerName=dc01
PSShowComputerName NoteProperty bool PSShowComputerName=True
RequiredServices NoteProperty Deserialized.System.ServiceProcess.Servi...
RunspaceId NoteProperty guid RunspaceId=5ed06925-8037-43ef-9072-...
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.Servi...
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.Servi...
ServiceType Property System.String {get;set;}
Site Property {get;set;}
StartType Property System.String {get;set;}
Status Property System.String {get;set;}
请注意,反序列化对象缺少大多数方法。 缺少这些方法,因为这些对象不是实时的。 当对远程计算机执行命令时,它们是对象状态的惰性快照。 例如,不能使用反序列化对象启动或停止服务,因为它不再有权访问所需的方法。
但是,这并不意味着不能使用类似于Stop()
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()
方法停止服务。
在前面的示例中,使用 Stop()
方法来强调一个观点。 有些人错误地认为不能在 PowerShell 远程处理中使用方法。 虽然无法对返回到本地会话的反序列化对象调用方法,但可以在远程会话中调用它们。
PowerShell 会话
在上一部分的最后一个示例中,使用 Invoke-Command
cmdlet 运行了两个命令。 这种情况导致建立并终止了两个独立的会话。 每个命令对应一个。
与 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 返回的对象之间有何区别?