抱歉,如果我是一个愚蠢的 powershell 菜鸟,但是工作显然无法写入终端有什么问题?我该如何解决?
# test.ps1
function myjob {
Write-Host "Hello, World!" # doesn't show
}
Start-Job -Name MyJob -ScriptBlock ${function:myjob}
Wait-Job MyJob
Remove-Job MyJob
抱歉,如果我是一个愚蠢的 powershell 菜鸟,但是工作显然无法写入终端有什么问题?我该如何解决?
# test.ps1
function myjob {
Write-Host "Hello, World!" # doesn't show
}
Start-Job -Name MyJob -ScriptBlock ${function:myjob}
Wait-Job MyJob
Remove-Job MyJob
听起来您正试图Write-Host
从后台作业直接、同步地写入控制台(终端)。
但是,PowerShell作业不允许直接访问调用者的控制台。 任何输出 - 甚至到 PowerShell主机(如果在一个控制台中运行,它在前台使用的是控制台)都通过 PowerShell 的输出流系统进行路由(请参阅概念about_Redirection帮助主题)。
因此,您始终需要Receive-Job
cmdlet 才能接收PowerShell 作业的输出。
以下示例同步接收作业输出,即阻塞执行,直到作业完成(-Wait
)然后将其删除(-AutoRemoveJob
);请参阅底部的异步(轮询,非阻塞)方法。
$null = Start-Job -Name MyJob -ScriptBlock { Write-Host "Hello, World!" }
Receive-Job -Wait -AutoRemoveJob -Name MyJob
Write-Host
警告在工作中重复使用:
在前台使用中,Write-Host
即使最初设计用于发送到主机(控制台)的输出也可以通过信息流(其编号为6
,在 PSv5+ 中可用)重定向或捕获;例如:
# OK - no output
Write-Host 'silence me' 6>$null
Write-Host
但是,从 PowerShell 7.2.1 开始,无法重定向或捕获通过(基于子进程的)后台作业接收的输出:
# !! `silence me` still prints.
Start-Job { Write-Host 'silence me' } | Receive-Job -Wait -AutoRemoveJob 6>$null
相比之下,当使用(通常更可取的)基于线程的后台作业(与基于子进程的后台作业相反)时,可以通过以下方式重定向/捕获它:Start-ThreadJob
# OK - no output
Start-ThreadJob { Write-Host 'silence me' } | Receive-Job -Wait -AutoRemoveJob 6>$null
等待作业以非阻塞方式完成,并在作业输出可用时传递:
# Start a simple job that writes a "." to the host once a second,
# for 5 seconds
$job = Start-Job $job -ScriptBlock {
1..5| ForEach-Object { Write-Host -NoNewLine .; Start-Sleep 1 }
}
"Waiting for job $($job.Id) to terminate while passing its output through..."
do {
$job | Receive-Job # See if job output is available (non-blocking) and pass it through
Start-Sleep 1 # Do other things or sleep a little.
} while (($job | Get-Job).State -in 'NotStarted', 'Running')
"`nJob terminated with state '$($job.State)'."
$job | Remove-Job # Clean up.
注意:在这个简单的情况下,预期的终止状态是Completed
(没有发生或仅发生非终止错误)或Failed
(生成了脚本终止错误throw
(并且未在作业中捕获))。
[System.Management.Automation.JobState]
枚举。返回的作业对象Start-Job
- 而不是通过参数自行选择的名称-Name
- 用于与作业交互。这消除了给定的可能存在多个作业的歧义-Name
,所有这些作业都将成为目标。