我正在开发一个自定义PowerShell模块,我想在与另一台计算机的远程会话的上下文中使用它。以下代码(显然不起作用)解释了我想要实现的目标:
import-module .\MyCustomModule.psm1
$session = new-pssession -computerName server01
invoke-command -session $session -scriptblock {
<# use function defined in MyCustomModule here #>
}
第一个问题是,是否完全可以实现这种情况?我的意思是我只希望我的自定义模块实际存在于我的机器上,而不是远程服务器上。
我找到了this thread,但我没有管理它 - 它不允许从远程机器创建一个会话回到本地会话。可能,我面对在该线程的评论中提到的配置限制......此外,作者提到了对我的解决方案至关重要的性能影响......
如果那可能,那怎么样?
PowerShell的版本目前不是约束 - 如果解决方案仅在PS 3.0中可用 - 我可以忍受这个。
这个问题有一些很好的评论,我花了一些时间研究解决问题的各种方法。
首先,我最初要求的是不可能的。我的意思是,如果你采用模块方式,那么模块应该实际存在于目标机器上,以便能够将Import-Module
进入远程会话。
为了进一步抽象我的问题,我正在尝试为产品部署创建一个可重用的基于PowerShell的框架。这将是一种推送式部署,这意味着我们鼓励人们在本地计算机上运行一些脚本以部署到某个远程服务器。据我调查这个区域,有两种可能的方式对常识很友好。
要遵循的流程:
*.psm1
)PSModulePath
变量以包括新模块位置Invoke-Command -Session $s -ScriptBlock {...}
Import-Module CustomModule
开始 - 它将在远程机器上搜索CustomModule
,显然会找到它以下是喜欢这种方法的原因:
考虑以下因素很重要:
xcopy
。此外,交付机制应该支持升级/降级和(最好)多实例安装,但这与我的任务相关而不是一般的问题。要遵循的流程:
Invoke-Command -Session $s -FilePath .\myscript.ps1
将脚本中定义的函数加载到远程会话Invoke-Command -Session $s -ScriptBlock {...}
并参考您的自定义函数 - 它们将在会话中存在以下是这种方法的优点:
当然,这并不理想:
最后,我应该说远程机器仍然需要为远程处理做好准备。这就是我的意思:
Set-ExecutionPolicy Unrestricted
Enable-PSRemoting
这是另一种方法:在远程会话中重新创建模块,而不复制任何文件。
我没有尝试处理模块之间的依赖关系,但这似乎适用于简单的自包含模块。它依赖于本地会话中可用的模块,因为这使得确定导出更容易,但是通过一些额外的工作,它也可以用于模块文件。
function Import-ModuleRemotely([string] $moduleName,[System.Management.Automation.Runspaces.PSSession] $session)
{
$localModule = get-module $moduleName;
if (! $localModule)
{
write-warning "No local module by that name exists";
return;
}
function Exports([string] $paramName, $dictionary)
{
if ($dictionary.Keys.Count -gt 0)
{
$keys = $dictionary.Keys -join ",";
return " -$paramName $keys"
}
}
$fns = Exports "Function" $localModule.ExportedFunctions;
$aliases = Exports "Alias" $localModule.ExportedAliases;
$cmdlets = Exports "Cmdlet" $localModule.ExportedCmdlets;
$vars = Exports "Variable" $localModule.ExportedVariables;
$exports = "Export-ModuleMember $fns $aliases $cmdlets $vars;";
$moduleString= @"
if (get-module $moduleName)
{
remove-module $moduleName;
}
New-Module -name $moduleName {
$($localModule.Definition)
$exports;
} | import-module
"@
$script = [ScriptBlock]::Create($moduleString);
invoke-command -session $session -scriptblock $script;
}
如果没有任何“黑客攻击”,我不相信这个盒子是正确的。聪明的举动可能是将模块放在像文件服务器这样的公共位置,并在需要时将其导入服务器。例如:
$session = new-pssession -computerName server01
invoke-command -session $session -scriptblock {
#Set executionpolicy to bypass warnings IN THIS SESSION ONLY
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
#Import module from public location
Import-Module \\fileserver\folders\modulelocation...
<# use function defined in MyCustomModule here #>
}
如何使用qazxsw poi从自定义函数中创建scriptblock并将其发送到目标服务器
Invoke-command
感谢这个帖子,它很有帮助......
但我实际上改写了这个功能。
请注意,此帖子中的原始函数或此重写函数包含模块清单数据。所以你不能依赖模块上的版本检查。
Import-module YourModule
$s = [scriptblock]::Create($(get-item Function:\Your-ModuleFunction).Definition)
Invoke-Command -ScriptBlock $s -Computername s1,s2,sn