我有一个针对不同分支运行的Pull Request验证构建,即该构建的多个并发实例是很常见的事情。
构建所做的一件事是安装模块。现在,我可以在构建代理上修改配置文件并从那里安装模块,但是我想避免任何额外的构建代理配置。因此,我的构建在当前用户范围内安装了一个模块。
我注意到Install-Module
并发调用时似乎并不安全-可能会因各种不同而奇怪的错误消息而失败。
现在,我使用在获取之前和之后释放的命名互斥体来解决此问题,但这会导致糟糕的性能-代码有时需要等待30秒或更长时间。 那么,如何解决这个问题呢?如何同时安全且性能良好地同时安装Powershell模块?
编辑1
令人沮丧。我正在尝试使用Set-PSDebug -Trace 2
跟踪并发安装,但是显然Install-Module
有很多Write-Debug
调用,这些调用本身对并发执行并不安全!因此,试图追踪实际上会使事情变得更糟。
答案 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-Module
或Import-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