如何让PowerShell函数streamMonitor多实例并行运行?
问题描述
我的streamMonitor函数(位于streamMonitor.ps1文件)功能正常,希望在invokingStream.ps1中调用该函数的多个实例实现并行运行。但运行invokingStream.ps1时进程直接结束,未按预期持续执行,使用的是PowerShell 5.1,请问需要修改什么才能实现并行运行?
streamMonitor.ps1 函数代码
function streamMonitor { [cmdletbinding()] param( [string]$directoryPath, [string]$scriptToRestartPath ) while ($true) { Write-Output "Monitoring directory: $directoryPath" Write-Output "Script to restart: $scriptToRestartPath" # 获取当前时间 $currentTime = Get-Date # 获取目录内最新文件的创建时间 $latestCreationTime = Get-ChildItem -Path $directoryPath -Recurse | Where-Object { !$_.PSIsContainer } | Sort-Object CreationTime -Descending | Select-Object -First 1 | ForEach-Object { $_.CreationTime } # 确保$latestCreationTime不为空 if ($null -eq $latestCreationTime) { Write-Output "No files found in the directory." return } # 检查最新文件创建时间是否在30秒内 $timeDifference = New-TimeSpan -Start $latestCreationTime -End $currentTime if ($timeDifference.TotalSeconds -gt 30) { # 30秒内无变化,重启指定脚本 Write-Output "No changes detected within the last 30 seconds. Restarting script..." Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$scriptToRestartPath`"" -NoNewWindow } else { Write-Output "Changes detected within the last 30 seconds. No action taken." } Start-Sleep -Seconds 30 continue } }
原 invokingStream.ps1 调用代码
#Invoking Functions in Parallel $job1 = Start-Job -ScriptBlock { . C:\pathto\streamMonitor.ps1 streamMonitor -directoryPath "C:\pathto\stream1" -scriptToRestartPath "C:\pathto\stream1.bat" } $job2 = Start-Job -ScriptBlock { . C:\pathto\streamMonitor.ps1 streamMonitor -directoryPath "C:\pathto\stream2" -scriptToRestartPath "C:\pathto\stream2.bat" } $job3 = Start-Job -ScriptBlock { . C:\pathto\streamMonitor.ps1 streamMonitor -directoryPath "C:\pathto\stream3" -scriptToRestartPath "C:\pathto\stream3.bat" }
解决方案
问题核心是Start-Job创建的后台作业不会阻塞主脚本执行,主脚本启动完所有作业后直接退出,而后台作业虽然在运行,但你看不到输出也无法保持主进程存活。需要做以下修改:
1. 添加作业等待逻辑
在主脚本末尾添加等待逻辑,让主进程持续运行,直到所有后台作业终止(你的函数是无限循环,所以主进程会一直保持存活):
# 实时接收作业输出并保持主进程运行 while ($true) { # 获取所有作业的输出并保留日志(-Keep参数避免输出被清空) Get-Job | Receive-Job -Keep # 每5秒检查一次输出 Start-Sleep -Seconds 5 }
如果不需要实时查看输出,仅需保持主进程存活,也可以用:
# 等待所有作业完成(无限循环的作业会持续运行,主进程也会保持存活) Get-Job | Wait-Job
2. 替换Write-Host为Write-Output
Write-Host的输出不会被后台作业捕获,改用Write-Output才能通过Receive-Job获取作业的运行日志。
修改后的完整 invokingStream.ps1
# 启动并行监控作业 $job1 = Start-Job -ScriptBlock { . C:\pathto\streamMonitor.ps1 streamMonitor -directoryPath "C:\pathto\stream1" -scriptToRestartPath "C:\pathto\stream1.bat" } $job2 = Start-Job -ScriptBlock { . C:\pathto\streamMonitor.ps1 streamMonitor -directoryPath "C:\pathto\stream2" -scriptToRestartPath "C:\pathto\stream2.bat" } $job3 = Start-Job -ScriptBlock { . C:\pathto\streamMonitor.ps1 streamMonitor -directoryPath "C:\pathto\stream3" -scriptToRestartPath "C:\pathto\stream3.bat" } # 实时接收作业输出并保持主进程存活 while ($true) { Get-Job | Receive-Job -Keep Start-Sleep -Seconds 5 }
额外说明
- 如需停止所有后台作业,可在另一个PowerShell窗口执行:
Get-Job | Stop-Job | Remove-Job - 查看作业详细状态,使用
Get-Job命令
内容的提问来源于stack exchange,提问作者Luke Lopez
相关产品推荐
相关产品推荐

