16. PowerShell -- 远程管理(2)


PowerShell2.0 远程管理之启用和执行命令

本文涉及的内容:

  • 如何启用和禁用PowerShell的远程管理。

  • 如何在工作组和混合域环境下配置计算机。

  • 如何使用Invoke-Command cmdlet用于在远程主机上执行命令,创建持久线程,在多个命令间同一线程传递的变量和参数。

  • 如何以后台任务的形式实现,用户可以在执行较费时的命令时使用它,并在执行完毕后使用命令回调执行结果。

1 启用和禁用远程管理

PowerShell2.0中能通过在PowerShell提示符下执行下列的cmdlet启用远程管理

PSC:\> Enable-PSRemoting

该cmdlet会向用户询问几个问题如下图1所示

技术分享

当执行该cmdlet时执行了以下操作,其中包括:

1. 启动或重新启动(如果已启动) WinRM 服务。

2. 将 WinRM 服务类型设置为自动启动。

3. 在本地计算机上创建一个侦听器以接受任意 IP 地址上的请求。

4. 对 WS-Management 流量启用防火墙例外(仅适用于 http),如果要启用PS远程管理,此时网络位置不能被设置为public,因为Windows 防火墙例外不能在网络位置是public时被启用。

5.启用所有注册的PS线程配置信息。

默认情况下,WinRM只启用http传输用于接收远程请求。用户可以使用winrm命令或New-WSManIntance cmdlet手动启用https传输。

【提示】

默认情况下,PowerShell远程管理使用5985(http)和5986(https)端口。可以通过使用Set-Item cmdlet修改wsman:\Localhost\listener\listener*\port对端口号进行设置,需要注意的是这样的操作将会改变系统中每个WinRM监听器端口号。

当给Enable-PSRemotingcmdlet增加-force参数后执行将会在静默状态下启用远程管理,PowerShell远程管理是不能通过远程启用的。

1.1 测试PowerShell远程管理

如果远程管理被启用了,可以使用下面的cmdlet查看:

PSC:\ > Enter-PSSession –ComputerName localhost

用户将会看到如下图2所示的提示符:

技术分享

【提示】

PowerShell线程(PS Session)是运行远程命令和脚本的环境。

PowerShell2.0提供了各式各样的cmdlet管理这些线程。可以使用Get-Command –noun PSSession命令查看所有与PSSession相关的cmdlet。

New-PSSession和Enter-PSSession有一个参数-sessionOption用于指定自定义线程选项,备选的选项有:

IdleTimeOut定义远程主机的过期时间,在未收到本地计算机包括心跳信号在内的任何通信数据的情况下,PSSession将会被关闭

OpenTimeOut定义客户端主机等待线程建立连接的超时时间,一旦超时,建立连接的命令将会失败。

OperationTimeOut定义能在PSSession中运行任何操作的最长时间,一旦超时,操作将会失败。

SkipCACheck指定在通过HTTPS连接时,客户端不验证服务器证书是否由受信的CA签发

SkipCNCheck指定服务器的证书普通名(CN,CommonName)不需要匹配服务器的主机名,这个选项只是用于通过HTTPS协议传输的远程操作。

SkipRevocationCheck不验证主机证书的撤回状态。

1.2在工作组环境中远程管理

只通过运行Enable-PSRemoting cmdlet是直接无法连接到工作组中的计算机的。本质上来说是因为加入工作组的计算机所拥有的安全级别是比加入域中的计算机更严格。所以如果再加入工作组中的计算机,用户在创建远程线程之前需要启用相关的设置。

WindowsXP 用户需要确认将本地安全策略设置为网络登录经典鉴权。通过控制面板→管理工具→本地安全策略,定位到“本地策略”→“安全选项”双击“网络访问:本地帐户的共享和安全模式”,并设置为“经典-本地用户以自己的身份验证”,效果如下图3所示:

技术分享

修改WSMan信任主机设置

在所有加入工作组的计算机——包括Windows XP,WindowsVista或更高版本,用户需要使用如下命令增加所有远程客户端的IP地址到受信主机清单中:

PSC:\ > Set-item wsman:localhost\client\trustedhosts –value *

使用*用于将所有主机添加为受信主机,如果需要指定特定的主机可以使用下面的命令:

PSC:\ > Set-item wsman:localhost\client\trustedhosts –valueCopmuter1,Computer2

如果需要添加指定域名下的所有主机可执行下面的命令:

PSC:\ > Set-item wsman:localhost\client\trustedhosts –value *.testdomain.com

如果需要添加远程主机的IP地址到受信主机的清单:

PSC:\ > Set-item wsman:localhost\client\trustedhosts –value 10.0.0.1

一旦做了上面的更改,用户能用Enable-PSRemoting cmdlet在这些工作组中的主机。

1.3在混合域环境中使用远程管理

默认情况下,不同域下的用户即使是本地管理员组的成员仍然不能连接到其他域中的主机。这是因为从其他域的远程连接只是运行在独立的用户权限之上。为了能使不同域的主机可以连接到本地计算机,用户可以更改LocalAccountTokenFilterPolicy注册表键值(设置为1)来允许其他域的成员到本地计算机

PSC:\ > new-itemproperty -name LocalAccountTokenFilterPolicy -path `HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -propertyTypeDWord -value 1

1.4 在企业环境下启用远程管理

为了能在企业或域环境中的多台主机上启用远程管理,用户需要使用组策略,更多的信息可以从http://technet.microsoft.com/en-us/library/dd347642.aspx地址获取。

1.5禁用远程管理

用户可以使用Disable-PSRemoting在本地主机上禁用远程管理。Disable-PSRemoting将会使线程配置信息失效,这样的操作并不会移除所有Enable-PSRemoting创建的配置,包括WinRM的启用状态和为PS远程管理创建的监听器。

如果在本机上没有任何服务或组件需要WinRM服务,用户可以通过执行下列命令禁用WinRM服务:

Set-Servicewinrm -StartupType Manual

Stop-Servicewinrm

为了移除默认情况下WinRM在5985端口设置的监听器可以执行的下述命令:

Get-ChildItemWSMan:\localhost\Listener –Recurse | Foreach-Object { $_.PSPath } |Where-Object { (Get-Item "$_\Port").Value -eq 5985 } | Remove-Item

2 执行远程命令

在远程管理的情况下,有两种方式在远程主机上运行命令或脚本。包括Invoke-Command cmdlet和交互式远程线程。一旦用户在本机启用远程管理,用户就能用Invoke-Command cmdlet在本机或远程主机运行命令和脚本。

2.1 在本地或远程主机运行脚本块

用户能用下面的方式在本地和远程主机调用命令:

Invoke-Command-ComputerName WinServ-wfe -ScriptBlock {Get-Process}

脚本块此参数能用于指定在远程主机运行的一系列命令。如果要在本地执行命令,则ComputerName参数不是必须的。如果用户需要在多个远程主机上执行相同的命令,用户能如下例所示通过逗号分隔的ComputerName参数或使用文本文件将主机清单传递给cmdlet:

Invoke-Command-ComputerName WinServ-wfe, SQL-Server2008 -ScriptBlock {Get-Process}

Invoke-Command-ComputerName (get-content c:\scripts\servers.txt) -ScriptBlock {Get-Process}

这种方式也被称之为散开式或一对多远程管理。用户能用一条命令在多台主机上执行相同的命令。

脚本块中所有的命令和变量均会在远程计算机上运行。如果用户采用类似于-ScriptBlock {Get-Process –Name $procName},PowerShell认为远程计算机线程中$procName变量已经定义过了。用户能通过使用Invoke-Command命令,将本地计算机上的变量传递到远程线程。

2.2 传递变量到远程线程

前面的例子中,用户可以传递要寻找的进程名作为变量。ArgumentList参数能帮助用户传递到远程线程中:

$procName= "powershell"

Invoke-Command-ComputerName (get-content c:\scripts\servers.txt) ` -ScriptBlock {param($Name) Get-Process -Name $Name} –ArgumentList $procName

上面的例子中可以显示如何使用-ArgumentList参数传递本地变量到远程线程。

2.3 通过Invoke-Command使用持久线程

用户可以使用带-ComputerName参数的Invoke-Command建立临时的线程执行远程命令。会在每次使用Invoke-Command cmdlet时,都会重新建立线程。在只是执行简单、为数不多的命令时可能无所谓,但是如果要执行大量命令和脚本时将会非常的耗时费力。为了避免这种情况,就需要使用持久线程,用户能使用New-PSSession cmdlet创建对远程主机的持久连接。

$s =New-PSSession -ComputerName WinServ-wfe

此时,$s包含持久连接的线程细节,可以使用$s在远程主机上调用命令语法如下:

Invoke-Commad-Session $s -ScriptBlock {get-Process}

当在远程组合机上执行命令时,$s会包含所有创建和修改的变量。这样以$s作为线程的后续执行的命令能够访问所有在远程主机上创建和更新的变量,如下例所示:

$s =new-pssession -computername WinServ-wfe

Invoke-Command-Session $s -ScriptBlock {$fileCount = (Get-ChildItem D:\ -Recurse).Count}

invoke-command-session $s -scriptblock {$fileCount}

用户能访问$fileCount变量,因为是使用了持久线程执行命令。如果只是使用-ComputerName调用命令这是不可能实现的。

2.4作为后台任务运行远程命令

前面的例子中获取远程主机上所有D:\下的文件数量,如果包含的文件数量很大的情况下将会很耗时,这样就需要等待远程命令完成执行。为了避免这一点,用户可以使用-AsJob参数使命令作为远程主机的后台任务。命令格式如下所示:

Invoke-Command-ComputerName WinServ-wfe -ScriptBlock {(Get-ChildItem D:\ -Recurse).Count}–asJob

执行后效果如下图4所示:

技术分享

当用户使用带-AsJob参数的Invoke-Command cmdlet时,远程主机上的后台任务将会被创建和运行,在后台任务被创建后,可以使用*-job cmdlet管理任务对象。

比如,用户可以使用Get-Job监控任务的状态并且一旦任务状态变为完成,就可以使用Receive-Jobcmdlet获取指定脚本块的输出。

Get-Job–id 3 | Receive-Job

用户也能使用Start-Job在远程主机上用脚本块创建后台任务。然而,通过这样方式建立的任务的输出结果只会在远程主机上显示。当用户需要从该后台任务获取输出输出时,就需要在Invoke-Command调用的脚本块中使用Receive-Job cmdlet。

2.5 为远程管理指定凭据

前面的文章里,能够用在工作组中的计算机间使用PowerShell远程管理。在前面的例子中只是假定是使用管理员权限访问远程计算机,这样的方式可以在域中任何以管理员凭据登陆的计算机上在域环境中很好的工作,用户不需要显式的传递凭据给Invoke-Command。然而,这样的方式是无法在工作组环境下使用,需要传递凭据给Invoke-Command,如下例所示:

$cred= Get-Credential

Invoke-Command-ComputerName WinServ-wfe -ScriptBlock { Get-Process} -Credential $cred

在上面的例子中,Get-Credential会向用户索取访问远程主机的凭据,并使用该凭据调用Invoke-Commandcmdlet。


Function Get-DomainCredential()

{

         $domain=Get-DomainName

         $username= "$domain\administrator"

         $password= "123"

         $cred= New-Object System.Management.Automation.PSCredential -ArgumentList@($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))

         return$cred

}

参考:http://tech.ccidnet.com/art/302/20100701/2102911_1.html


本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1641915

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。