PowerShell 让本地变量兼容在本地和远程执行


当你在编写远程代码时,可能会遇到一些小的挑战,下面的示例会稍作说明。

function Get-Log($LogName='System', $ComputerName=$env:computername) 
{ 
	$code = { Get-EventLog -LogName $LogName -EntryType Error -Newest 5 } 
	$null = $PSBoundParameters.Remove('LogName') 
	Invoke-Command -ScriptBlock $code @PSBoundParameters 
} 

Get-Log函数支持从Windows事件日志中获取最新的5行错误事件日志,他被设计地支持本地执行,也可以发送至远程执行。

因此它可以接收可选参数 -ComputerName. 这个参数将会通过@PSBoundParameters 绑定,移交给Invoke-Command。只有用户真的指定 -ComputerName 参数了, Invoke-Command 才会执行. 否则, Invoke-Command 在本地执行代码. 这里稍微提一下,为什么要从变量$PSBoundParameters 中移除 -LogName ,因为这个变量不应当移交给Invoke-Command。因为$Code代码块已经包含了它。

同样会陪到另一个问题,在本地代码运行正常,一旦用户指定了-ComputerName,这些代码将会被发送至远程机器执行(前提条件是远程机器开启了PowerShell远程服务,并且您有足够的权限)。但是,此时$LogName 为空啊。因为它本来只是一个本地变量,并没有在远程机器上定义过。

在我们之前的文章中已经提到过,PowerShell 3.0中新增了前缀using,可以标记本地变量,让它提供远程支持。将脚本改为:

$code = { Get-EventLog -LogName $Using:LogName -EntryType Error -Newest 5 }

这样一来远程执行可以顺利过关, 但是现在在本地执行又会失败。 因为 “using” 只有远程执行时才会识别。针对这个问题有一个解决方案是将本地变量已参数列表的形式传递给远程会话,下面的修改的代码终于可以支持本地执行和也可兼容远程执行。

function Get-Log($LogName='System', $ComputerName=$env:computername)
{
    $code = { param($LogName) Get-EventLog -LogName $LogName -EntryType Error -Newest 5
    $null = $PSBoundParameters.Remove('LogName')
    Invoke-Command -ScriptBlock $code.GetNewClosure() @PSBoundParameters -Argument $LogName
}

PS> Get-Log
PS> Get-Log -computername storage1

原文链接:http://powershell.com/cs/blogs/tips/archive/2012/10/26/executing-code-locally-and-remotely-using-local-variables.aspx

本文链接: http://www.pstips.net/executing-code-locally-and-remotely-using-local-variables.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

电子邮件地址不会被公开。 必填项已用*标注