如何同时安装Powershell模块?

时间:2019-05-15 05:20:54

标签: powershell concurrency module

我有一个针对不同分支运行的Pull Request验证构建,即该构建的多个并发实例是很常见的事情。

构建所做的一件事是安装模块。现在,我可以在构建代理上修改配置文件并从那里安装模块,但是我想避免任何额外的构建代理配置。因此,我的构建在当前用户范围内安装了一个模块。

我注意到Install-Module并发调用时似乎并不安全-可能会因各种不同而奇怪的错误消息而失败。

现在,我使用在获取之前和之后释放的命名互斥体来解决此问题,但这会导致糟糕的性能-代码有时需要等待30秒或更长时间。 那么,如何解决这个问题呢?如何同时安全且性能良好地同时安装Powershell模块?

编辑1

令人沮丧。我正在尝试使用Set-PSDebug -Trace 2跟踪并发安装,但是显然Install-Module有很多Write-Debug调用,这些调用本身对并发执行并不安全!因此,试图追踪实际上会使事情变得更糟。

1 个答案:

答案 0 :(得分:0)

显然,Install-Module完全不安全,可以在同一代理上运行多个构建的构建期间运行。看起来使用命名的Mutex是最安全的方法。

编辑1

在多线程环境中,如果没有显式互斥锁,调用以下命令并不安全:

  • Install-Module
  • Import-Module
  • Get-PSRepository,不带参数

也许更多。在我的代码中,我调用了所有三个命令,并且发现所有这些命令必须在一起使用同一个互斥锁,即这些组合不起作用:

无法使用#1

$mtx.WaitOne()
try
{
    Install-Module ...
}
finally
{
    $mtx.ReleaseMutex()
}
Import-Module ...
Get-PSRepository ...

无法运行#2

$mtx.WaitOne()
try
{
    Install-Module ...
    Import-Module ...
}
finally
{
    $mtx.ReleaseMutex()
}
Get-PSRepository

唯一安全的选择似乎就是这个:

$mtx.WaitOne()
try
{
    Install-Module ...
    Import-Module ...
    Get-PSRepository
}
finally
{
    $mtx.ReleaseMutex()
}

这是令人惊讶的,因为我不希望Install-ModuleImport-Module影响Get-PSRepository,但是它们却以某种方式起作用:

   ParameterBindingException: A parameter cannot be found that matches parameter name 'Provider'.
   at Get-PSRepository<Process>, C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1: line 4496
   at Use-ModuleFB22C60E, C:\Users\mkharitonov\AppData\Local\Temp\fb22c60e-a0c5-48b3-953a-0b580c6a2f5e\m_deadbeef_.ps1: line 167
   at <ScriptBlock>, <No file>: line 4