如何防止同一PowerShell 7脚本的多个实例?
在构建服务器上的上下文
,将启动PowerShell 7脚本script.ps1
,并将在远程计算机的后台运行。
我想要
一个保险箱以确保script.ps1
脚本最多1个实例始终在构建服务器或远程计算机上运行。
我尝试的是:
我尝试处理PowerShell 7背景作业(通过执行script.ps1
作为包装脚本中的作业wrapper.ps1
),但是这没有解决问题,因为在其他PowerShell会议上没有继续(也无法访问)工作。
我尝试的是这样:
# inside wrapper.ps1
$running_jobs = $(Get-Job -State Running) | Where-Object {$_.Name -eq "ImportantJob"}
if ($running_jobs.count -eq 0) {
Start-Job .\script.ps1 -Name "ImportantJob" -ArgumentList @($some_variables)
} else {
Write-Warning "Could not start new job; Existing job detected must be terminated beforehand."
}
重申一下,问题是$ running_jobs
仅返回当前会话中运行的作业,因此此代码仅限制每个会话的一个作业,允许多个实例如果多个会议被错误打开,请进行。
我还尝试了:
我尝试查看get-ciminstance
:
$processes = Get-CimInstance -ClassName Win32_Process | Where-Object {$_.Name -eq "pwsh.exe"}
虽然这确实返回了当前运行的PowerShell实例,但这些元素没有对正在执行的脚本进行任何信息,如我运行后所示:
foreach ($p in $processes) {
$p | Format-List *
}
因此,我迷路了,我觉得我缺少一些东西。 感谢任何帮助或建议。
Context
On a build server, a PowerShell 7 script script.ps1
will be started and will be running in the background in the remote computer.
What I want
A safenet to ensure that at most 1 instance of the script.ps1
script is running at once on the build server or remote computer, at all times.
What I tried:
I tried meddling with PowerShell 7 background jobs (by executing the script.ps1
as a job inside a wrapper script wrapper.ps1
), however that didn't solve the problem as jobs do not carry over (and can't be accessed) in other PowerShell sessions.
What I tried looks like this:
# inside wrapper.ps1
$running_jobs = $(Get-Job -State Running) | Where-Object {$_.Name -eq "ImportantJob"}
if ($running_jobs.count -eq 0) {
Start-Job .\script.ps1 -Name "ImportantJob" -ArgumentList @($some_variables)
} else {
Write-Warning "Could not start new job; Existing job detected must be terminated beforehand."
}
To reiterate, the problem with that is that $running_jobs
only returns the jobs running in the current session, so this code only limits one job per session, allowing for multiple instances to be ran if multiple sessions were mistakenly opened.
What I also tried:
I tried to look into Get-CimInstance
:
$processes = Get-CimInstance -ClassName Win32_Process | Where-Object {$_.Name -eq "pwsh.exe"}
While this does return the current running PowerShell instances, these elements carry no information on the script that is being executed, as shown after I run:
foreach ($p in $processes) {
$p | Format-List *
}
I'm therefore lost and I feel like I'm missing something.
I appreciate any help or suggestions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我喜欢使用
$ env:programData
使用companyname \ projectName
方案的位置定义配置路径,以便我可以将“每个系统”配置放置。您可以将类似的方案与定义位置使用类似的方案来存储脚本运行并在其末尾删除时创建的锁定文件(如注释中所建议的)。
然后,如果需要,则由您添加其他检查(如果锁定在锁定仍然存在的情况下脚本过早退出会发生
?
什么 一个时间表和设置“如果任务已经运行,则适用以下规则:不启动新实例”。从那里开始,您没有调用原始脚本,而是调用刚刚启动计划任务的代理脚本。
I like to define a config path in the
$env:ProgramData
location using aCompanyName\ProjectName
scheme so I can put "per system" configuration.You could use a similar scheme with a defined location to store a lock file created when the script run and deleted at the end of it (as suggested already within the comments).
Then, it is up to you to add additional checks if needed (What happen if the script exit prematurely while the lock is still present ?)
Example
Alternatively, on Windows, you could also use a scheduled task without a schedule and with the setting "If the task is already running, then the following rule applies: Do not start a new instance". From there, instead of calling the original script, you call a proxy script that just launch the scheduled task.