代码改变世界

PowerShell 2.0在远程主机上运行命令和脚本

2010-12-11 02:16 by @天行健中国元素, ... 阅读, ... 评论, 收藏, 编辑

在前面的文章里关于持久远程线程的讨论中,曾经介绍了如何在本地主机上进入远程线程并执行命令。如果没有显式的终止线程的情况下,用户能在本地计算机上执行远程主机的命令,而PowerShell的提示符能够直接反映当前所使用线程的状况。在本章将会介绍PowerShell的内置特性,这些特性能够使用户在远程主机上运行命令和脚本。

通过使用交互式远程管理可以克服使用Invoke-Command的一些缺点,然而这种方法也是有其局限性的。在交互式远程管理中,用户需要显式的进入或退出远程线程,这就意味着,同时只能连接到一个远程主机上,而且只能访问对应远程主机上的cmdlet和模块。如果需要让不同的cmdlet在不同的主机上都可以执行,这就做不到了。

比如,有两台主机分别各自安装了Exchange 2010和SharePoint 2010,如果用户需要访问两台主机上各自可用的cmdlet,两台主机和本机之间均会建立一个本地线程。使用Invoke-Command会建立到远程主机的线程,并通过该线程发送脚本块执行。尽管通过交互式远程管理可以指定特定的远程线程,但是同一时间只能连接到Exchange 2010主机或者是SharePoint 2010主机当中的一台,无法实现各主机间cmdlet的共享,此时隐式远程管理就很重要了。

隐式远程管理能将远程的命令带到本地线程中,一旦将远程命令带到本地就不需要考虑PS线程的细节了。用户可以同时导入很多远程线程到本地线程,这样就可以实现在同一本地线程中访问不同产品的技术,PowerShell会在后台为用户关注具体的执行细节。

创建隐式远程管理

首先可以使用New-PSSession创建持久PS线程,接下来将该线程的远程命令导入到本地线程中,具体代码如下所示:

$s = New-PSSession -ComputerName WinServ-wfe

Import-PSSession -Session $s

默认情况下,Import-PSSession会导入除与当前线程中重名的命令外所有的命令,如果要导入所有的命令,需要使用-AllowClobber参数,在导入到过程中用户能看到控制台顶端会有进度条显示导入进度。如果用户导入的与本地线程同名的命令,导入的命令会隐藏或替换原始命令。这是因为导入的线程将会在导入之前将cmdlet转换为函数,而函数的优先级是高于cmdlet的,这样导入命令的优先级将会高于本地同名命令,在导入线程之后这些命令将会被导入。

对于导入的远程命令优先级,别名将会是个例外,本地线程这种原始别名的优先级会高于导入的别名。

导入远程线程时避免命名冲突

Import-PSSession提供了-Prefix参数用于为导入命令在其名词添加指定的前缀,如下例所示:

Import-PSSession -Session $s -Prefix RS

当从远程主机导入cmdlet时会为每个cmdlet添加RS前缀,如果Get-Command用这样的方式导入到本地线程中时需要通过调用Get-RSCommand来调用该cmdlet,PowerShell将会在远程主机上隐式运行该命令。

前面的章节中曾讨论过PowerShell在后台管理隐式远程管理,Invoke-Command会在每次执行远程命令前后,创建和销毁PS线程,对于隐式远程管理也是这样。以这种形式执行远程命令会比较缓慢,为了避免这种情况,Import-PSSession会在本地线程中向所有导入的命令添加-asJob参数。例如:

$s = New-PSSession -ComputerName WinServ-wfe

Import-PSSession -Session $s -Prefix RS

Get-RSProcess -asJob

这会将Get-RSProcess作为后台任务在远程主机运行,需要强调的是原始Get-Process是没有-asJob参数的,这里的-asJob只是作为本地线程传递给远程主机时使用的。

向本地线程中导入模块和管理单元

$s = New-PSSession -ComputerName WinServ-wfe

Invoke-Command -Session $s -ScriptBlock {Import-Module ActiveDirectory}

Import-PSSession -Session $s -Module ActiveDirectory

在上面的例子中首先创建了PS线程,用Invoke-Command导入了活动目录模块,并将线程导入本地线程。这样就使活动目录cmdlet在本地线程中可用了。

接下来连接到另外一个不同的远程线程并从该线程cmdlet:

$s = New-PSSession -ComputerName WinServ-wfe

Invoke-Command -Session $s -ScriptBlock {Add-PSSnapin Microsoft.SharePoint.PowerShell}

Import-PSSession -Session $s

此时在本地线程中,用户级可以访问一台主机上关于AD的cmdlet,也能访问另一台主机上的SharePoint 2010的cmdlet。这样就能通过本地线程同时管理两台主机了,而且不需要考虑创建和销毁线程的问题,PowerShell会替用户处理这些。

隐式远程管理的局限性

使用隐式远程管理时,用户不能导入变量或者PowerShell提供者,用户不能。Import-PSSession用Invoke-PSSession运行远程命令,可能会比较缓慢,因此所有导入的命令支持-asJob参数将命令作为远程主机上的后台任务执行,关于-asJob参数的用法可以参照前几篇文章中的具体介绍。

总结

隐式远程管理会将远程的命令带到本地,这项技术可以被用于导入在本地PowerShell环境中不存在的模块和管理单元,在本章中介绍了如何创建隐式远程线程以及用于Import-PSSession cmdlet的相关参数。隐式远程管理可以看作是将远程cmdlet缓存到本地,就可以同时将多台主机的cmdlet缓存到本地(当然是在考虑不重名的情况下),每个cmdlet在本地会有对应的隐射关系对应到特定远程主机上特定的cmdlet,在本地对cmdlet最终会通过远程管理机制传递到远程主机进行执行。如果是在重名的情况下,远程引入的cmdlet会在本地以函数的形式存在,故而通常的优先级会被本地cmdlet要高。因而在导入远程cmdlet之前需要为远程cmdlet在本地预设前缀,以方便与本地的cmdlet进行区分。

 

赛迪网地址:http://tech.ccidnet.com/art/302/20100702/2104175_1.html

 

作者: 付海军
出处:http://fuhj02.cnblogs.com
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://txj.shell.tor.hu/