我一直在探索Powershell中的作业(使用Start-Job、Get-Job、Receive-Job等命令)。
只要在同一个Powershell会话/窗口中,所有东西都可以正常工作,但是如果我打开新的Powershell窗口并执行“Get-Job”命令,它将不返回任何作业。
在Powershell中,难道没有任何方法可以启动后台作业、关闭窗口/会话,然后从另一个会话/窗口中访问它吗? 我有几个长时间运行的cmdlet,希望能够在后台启动并稍后检查,而无需保证使用相同的提示符。
我一直在探索Powershell中的作业(使用Start-Job、Get-Job、Receive-Job等命令)。
只要在同一个Powershell会话/窗口中,所有东西都可以正常工作,但是如果我打开新的Powershell窗口并执行“Get-Job”命令,它将不返回任何作业。
在Powershell中,难道没有任何方法可以启动后台作业、关闭窗口/会话,然后从另一个会话/窗口中访问它吗? 我有几个长时间运行的cmdlet,希望能够在后台启动并稍后检查,而无需保证使用相同的提示符。
更新
像我承诺的那样,我为您找到了另一个潜在的解决方案,DaveUK。今天我了解到PowerShell中的“RunSpaces”。我认为这可能是我们都在寻找的东西。它需要更多的工作,但使用 线程安全集合。以下示例摘自Boe Prox的 在PowerShell Runspaces之间共享变量和实时对象。他的文章详细描述了它做什么,如何工作,甚至可以执行多个“作业”。
使用 Debug-Runspace,您可以从其他会话监视它。我将努力在此答案中提供更多详细信息,以防该网站消失。但现在,希望这可以帮助到您。
$hash = [hashtable]::Synchronized(@{})
$hash.value = 1
$hash.Flag = $True
$hash.Host = $host
Write-host ('Value of $Hash.value before background runspace is {0}' -f $hash.value) -ForegroundColor Green -BackgroundColor Black
$runspace = [runspacefactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('Hash',$hash)
$powershell = [powershell]::Create()
$powershell.Runspace = $runspace
$powershell.AddScript({
While ($hash.Flag) {
$hash.value++
$hash.Services = Get-Service
$hash.host.ui.WriteVerboseLine($hash.value)
Start-Sleep -Seconds 5
}
}) | Out-Null
$handle = $powershell.BeginInvoke()
之前的回复
我已经尝试了几年来监视后台作业,而不依赖于主窗口保持打开,但是还没有找到一个非常规的解决方案。这让我相信使用内置的“-Job”功能不可能实现。因此,这并不是对主要问题的答案,而是我使用的一种解决方法。基本上,这是创建自己的“作业”设置,因为内置的功能不能按照我的想法运行。在这里需要注意的是,我很少在新进程中运行“单个作业”。通常是一个创建多个作业的进程。如果您需要长时间运行cmdlet,则可以将其启动到自己的PowerShell进程中,并将详细记录到文件中。
要在“后台进程”中运行多个作业,我会使用某种模板结构来构建您的cmdlet或作业。
示例Start-Process脚本:
$Jobs = @("Name1", "Name2")
ForEach ($JobName in $Jobs) {
$Job = Start-Job -Name $JobName -ScriptBlock {
# Code Here either static file or from variable
# With logic to stop a job if the file is removed, and create the file
}
}
$JobsRunning = $true
while ($JobsRunning) {
$JobsRunning = $false
ForEach ($JobName in $Jobs) {
if ((Get-Job -Name $JobName).State -ne "Completed") {
$JobsRunning = $true
}
}
Start-Sleep -seconds 120
}
}
exit
https://learn.microsoft.com/en-us/powershell/module/psscheduledjob/?view=powershell-5.1
已安排的工作似乎可以在任何PS会话中找到并检索,因此您可以使用它作为触发“工作”的方式,即使在关闭PS窗口后仍将继续运行。到目前为止,我发现唯一的问题是当ScheduledJob运行时,它会生成一个常规的Job,但该常规Job没有子Job,并且在完成之前没有可用的进度/状态。似乎不可能在运行时监视作业的状态/输出,因此这仍然不完美 :(
我建议您研究工作流程,因为它们被设计成具有强大的功能,可以处理长时间运行的任务,并且可以从故障/重新启动中恢复。但是,您也可以使用Invoke-Command
和-InDisconnectedSession
在后台运行命令或脚本,并再次从同一台或不同的计算机连接到它。试试这个例子。
创建会话
注意-在我的测试中,本地运行需要管理员权限,而远程运行则不需要。
$opt = New-PSSessionOption -IdleTimeout 86400000
$log = 'c:\temp\workflowtest.txt'
Invoke-Command -InDisconnectedSession -ScriptBlock {
1..10 | ForEach-Object {
"Current number is $_" | Add-Content $using:log
Start-Sleep -Seconds 1
write-host current iteration $_ -ForegroundColor Green
}
Get-Content $using:log
} -SessionOption $opt -SessionName testsession -ComputerName $env:COMPUTERNAME
关闭你从中运行此步骤的窗口,作为一个良好的测试步骤。
接收输出
打开一个新的 PowerShell 窗口(以管理员身份),并检索输出。如果还没有完成,它将一直接收,直到完成为止。
Get-PSSession -ComputerName $env:computername | Receive-PSSession
移除会话
Get-PSSession -ComputerName $env:computername | Remove-PSSession
Get-ChildItem -Path WSMAN:\localhost\Shell
进行检查,并根据您的环境进行增加。因此,如果他正在尝试同时在30台计算机上运行脚本,则需要提高限制。此外,断开连接取决于运行时间有多长,以及是否依赖VPN。 - Jim