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

如何用Start-RSJob循环整合4个脚本块并行运行并获取各任务状态?

解决方案

一、基于Start-RSJob的并行备份脚本(整合循环+全局状态监控)

1. 整合4个复制任务到循环

将4组源/目标路径整理为数组,通过循环批量启动RSJob,避免重复编写脚本块:

# 首次运行需安装RSJob模块
# Install-Module -Name PSScheduledJob -Force -AllowClobber

# 定义4组备份任务(替换为你的实际路径)
$backupTasks = @(
    @{ Source = "D:\SourceFolder1"; Destination = "E:\BackupFolder1" },
    @{ Source = "D:\SourceFolder2"; Destination = "E:\BackupFolder2" },
    @{ Source = "D:\SourceFolder3"; Destination = "E:\BackupFolder3" },
    @{ Source = "D:\SourceFolder4"; Destination = "E:\BackupFolder4" }
)

# 批量启动并行备份任务
$jobs = foreach ($task in $backupTasks) {
    Start-RSJob -ScriptBlock {
        param($src, $dest)
        # 带重试逻辑的Copy-Item,降低中断影响
        $retryCount = 3
        $success = $false
        do {
            try {
                Copy-Item -Path $src -Destination $dest -Recurse -Force -ErrorAction Stop
                $success = $true
                Write-Output "任务完成:$src -> $dest"
            }
            catch {
                Write-Warning "复制失败(剩余重试次数:$retryCount):$_"
                Start-Sleep -Seconds 10
                $retryCount--
            }
        } while (-not $success -and $retryCount -ge 0)
        if (-not $success) { Write-Error "任务最终失败:$src -> $dest" }
    } -ArgumentList $task.Source, $task.Destination
}

2. 定期检查所有任务状态

添加循环逻辑,每30秒扫描所有RSJob的运行状态,直到全部任务结束:

# 实时监控任务状态
while ($jobs.State -contains "Running") {
    Write-Host "`n当前任务状态($(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')):"
    foreach ($job in $jobs) {
        $statusTag = switch ($job.State) {
            "Running" { "*运行中*" }
            "Completed" { "已完成" }
            "Failed" { "*失败*" }
            default { $job.State }
        }
        # 显示任务对应的源/目标路径,方便识别
        $src = $job.ArgumentList[0]
        $dest = $job.ArgumentList[1]
        Write-Host "任务:$src -> $dest | 状态:$statusTag"
    }
    Start-Sleep -Seconds 30
}

# 任务全部结束后,输出最终状态并清理任务
Write-Host "`n所有备份任务已结束,最终状态:"
foreach ($job in $jobs) {
    $src = $job.ArgumentList[0]
    $dest = $job.ArgumentList[1]
    Write-Host "$src -> $dest : $($job.State)"
    # 读取任务输出日志
    if ($job.HasMoreData) { Receive-RSJob -Job $job }
    # 清理已完成的任务
    Remove-RSJob -Job $job
}

二、改用PowerShell 7+ ForEach-Parallel的修改方案

PowerShell 7及以上版本原生支持ForEach-Object -Parallel,无需额外安装模块,修改步骤如下:

  1. 给Windows Server 2012手动安装PowerShell 7+(官方包可直接部署)
  2. 替换RSJob逻辑为原生并行循环,示例脚本:
# 定义备份任务列表
$backupTasks = @(
    @{ Source = "D:\SourceFolder1"; Destination = "E:\BackupFolder1" },
    @{ Source = "D:\SourceFolder2"; Destination = "E:\BackupFolder2" },
    @{ Source = "D:\SourceFolder3"; Destination = "E:\BackupFolder3" },
    @{ Source = "D:\SourceFolder4"; Destination = "E:\BackupFolder4" }
)

# 使用原生并行执行备份
$results = $backupTasks | ForEach-Object -Parallel {
    $src = $_.Source
    $dest = $_.Destination
    $retryCount = 3
    $success = $false
    do {
        try {
            Copy-Item -Path $src -Destination $dest -Recurse -Force -ErrorAction Stop
            $success = $true
            [PSCustomObject]@{
                Source = $src
                Destination = $dest
                Status = "Completed"
                Message = "复制成功"
            }
        }
        catch {
            Write-Warning "复制失败(剩余重试次数:$retryCount):$_"
            Start-Sleep -Seconds 10
            $retryCount--
        }
    } while (-not $success -and $retryCount -ge 0)
    if (-not $success) {
        [PSCustomObject]@{
            Source = $src
            Destination = $dest
            Status = "Failed"
            Message = "最终失败:$_"
        }
    }
} -ThrottleLimit 4  # 限制并行数与任务数一致

# 输出最终结果
$results | Format-Table -AutoSize

实时监控说明

ForEach-Object -Parallel默认等待所有任务完成后返回结果,若需实时监控,可在并行块中写入本地日志文件,额外添加一个循环定期读取日志状态。

三、无需修改脚本传入目标路径的方法

方法1:使用脚本参数

在脚本开头添加参数定义,运行时通过命令行传入目标路径前缀:

param(
    [Parameter(Mandatory=$true)]
    [string]$TargetBasePath  # 目标路径根目录,比如"E:\NewSSD\BackupRoot"
)

# 基于传入的前缀自动生成任务目标路径
$backupTasks = @(
    @{ Source = "D:\SourceFolder1"; Destination = Join-Path $TargetBasePath "BackupFolder1" },
    @{ Source = "D:\SourceFolder2"; Destination = Join-Path $TargetBasePath "BackupFolder2" },
    @{ Source = "D:\SourceFolder3"; Destination = Join-Path $TargetBasePath "BackupFolder3" },
    @{ Source = "D:\SourceFolder4"; Destination = Join-Path $TargetBasePath "BackupFolder4" }
)

# 后续备份/监控逻辑保持不变...

运行脚本时传入参数:

.\BackupScript.ps1 -TargetBasePath "E:\NewSSD\MonthlyBackup"

方法2:读取外部配置文件

创建JSON配置文件BackupConfig.json:

{
    "BackupTasks": [
        {"Source": "D:\\SourceFolder1", "Destination": "E:\\BackupFolder1"},
        {"Source": "D:\\SourceFolder2", "Destination": "E:\\BackupFolder2"},
        {"Source": "D:\\SourceFolder3", "Destination": "E:\\BackupFolder3"},
        {"Source": "D:\\SourceFolder4", "Destination": "E:\\BackupFolder4"}
    ]
}

脚本中读取配置:

$config = Get-Content -Path ".\BackupConfig.json" | ConvertFrom-Json
$backupTasks = $config.BackupTasks

# 后续备份/监控逻辑保持不变...

修改目标路径时只需编辑JSON文件,无需改动脚本代码。

内容的提问来源于stack exchange,提问作者Chirag Raval

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:42:18