版本信息最后核对:2026-10-25
适合批量查询多台主机、下载或处理大量文件、同时跑多个互不依赖的检查,以及把长任务从交互会话里移开。远程批量任务用 Invoke-Command -AsJob,本机 I/O 等待型任务用后台作业或线程作业,大量小任务用 ForEach-Object -Parallel。
不适合需要窗口交互、需要共享大量可变状态、或必须严格顺序执行的任务。作业不是服务,宿主进程退出后本地作业通常就没了;需要持久化就用计划任务或真正的服务。
Start-Job、Get-Job、Wait-Job、Receive-Job、Stop-Job、Remove-Job。Start-Job 启动独立的 PowerShell 进程,隔离性好但启动和序列化开销大;变量、当前目录、函数和已加载模块不会自动继承。Start-ThreadJob 在同一进程的独立运行空间里跑,启动快、开销小,适合短任务;它没有进程级隔离,不能当作安全边界。Invoke-Command -AsJob 把命令发到远程会话执行,返回本地可管理的作业对象;远程会话断开后作业可能仍在远端运行,取决于会话配置。ForEach-Object -Parallel 用线程并行处理管道输入,默认最多 5 个并发,用 -ThrottleLimit 调整。Start-ThreadJob。ForEach-Object -Parallel 是 7.0 引入的,5.1 只能用作业、运行空间或工作流近似实现。Register-ScheduledJob)属于 Windows PowerShell 5.1;7.x 没有对应命令,持久化定时任务改用 schtasks 或任务计划程序。# 1. 启动后台作业,等待后只取一次输出,再删除作业
PS C:\> Start-Job -Name Slow -ScriptBlock { Start-Sleep 3; Get-Date }
PS C:\> Get-Job -Name Slow
PS C:\> Wait-Job -Name Slow | Receive-Job
PS C:\> Remove-Job -Name Slow
# 2. 作业不继承变量,参数用 -ArgumentList 传入
PS C:\> $path = 'C:\Windows'
PS C:\> Start-Job -ScriptBlock { param($p) Get-ChildItem $p -Filter *.log } -ArgumentList $path
# 3. 多主机远程执行并作为作业管理,主线程可以继续做别的事
PS C:\> Invoke-Command -ComputerName SRV01, SRV02 -AsJob -ScriptBlock { Get-Service Spooler }
PS C:\> Get-Job | Wait-Job | Receive-Job
# 4. 线程作业启动更快,适合同一进程内的短任务
PS C:\> Start-ThreadJob -ScriptBlock { (Get-Process).Count }
# 5. 7.x 并行管道;每个输入用 $using: 引用外部变量
PS C:\> 1..10 | ForEach-Object -Parallel { Start-Sleep -Milliseconds 200; "完成 $_" } -ThrottleLimit 5
# 6. 超时控制:Wait-Job 超时后返回空,要自己检查状态
PS C:\> Get-Job | Wait-Job -Timeout 30
PS C:\> Get-Job | Where-Object State -eq 'Running' | Stop-Job
# 7. 取结果时保留缓存,方便再次查看;最后统一清理
PS C:\> Get-Job | Receive-Job -Keep
PS C:\> Get-Job | Remove-Job -Force
Receive-Job 默认取走输出并从作业缓存中删除,第二次就看不到了;需要重复查看时加 -Keep。Start-Job 就报命令不存在,通常是这个原因;用 -InitializationScript 或 -ArgumentList 补齐。Start-Job 每次启动一个 PowerShell 进程,几十个小任务会产生明显开销;短任务优先线程作业或 7.x 的并行管道。Wait-Job -Timeout 超时不会抛异常,只是返回空;必须再查 Get-Job 的状态,否则会把“还在跑”当成“已完成”。Remove-Job 会让作业和输出缓存一直占内存;运行中的作业要 Stop-Job 后再删,必要时才用 -Force。Start-Job。ForEach-Object -Parallel 中不要修改外部可变对象;$using: 传进去的是副本,输出顺序也不保证与输入一致,需要排序就带序号。合上页面,先回答,再展开对照。
Start-Job 里的脚本为什么读不到主会话的变量和当前目录?Receive-Job 第二次没有输出,怎么排查和避免?Receive-Job 默认取走并清空输出缓存;用 -Keep 保留,或先保存结果变量。若仍为空,再查 Get-Job 的状态和错误流。
小程序版
微信扫码,随时查命令