You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 08:35:04