gpt4 book ai didi

multithreading - Powershell运行空间和颜色输出

转载 作者:行者123 更新时间:2023-12-02 23:47:25 25 4
gpt4 key购买 nike

简短的问题描述:

我需要脚本生成的其他Powershell运行空间的非散布输出。我需要能够在输出中设置单个线条的颜色。

详细问题描述:

我编写了一个脚本,以将更新部署到多个远程服务器上的供应商应用程序。最初,该脚本原本只打算一次部署一个更新,但是我有一个新的要求,即现在我要交互式处理多个更新。因此,我重新编写了脚本以使用运行空间,以便可以在所有服务器上打开 session ,对其进行初始化,然后对于每次更新,用户输入都会为每个初始化的 session 创建一个运行空间,并完成了部署工作。我以前使用过作业,但由于无法将PSSession传递给作业,因此不得不进入运行空间。

现在,我的脚本可以工作了,但是输出效果不理想。作业版本的输出很好,因为我可以调用Receive-Job并按线程将所有输出分组。另外,我可以使用写主机来记录输出,该输出允许进行彩色响应(即,更新失败时显示红色文本)。我已经能够获得作业的运行空间版本以按线程对输出进行分组,但只能使用写输出。如果我使用写主机输出,则会立即发生,从而导致散布输出,这是 Not Acceptable 。不幸的是,写输出不允许彩色输出。设置$ host.UI.RawUI.ForegroundColor也不起作用,因为如果在设置颜色的那一刻输出未发生,则效果不会发生。由于我的输出要到最后才出现,因此$ host设置不再起作用。

下面是一个演示脚本,演示了我的麻烦:

#Runspacing output example. Fix interleaving
cls

#region Setup throttle, pool, iterations
$iterations = 5
$throttleLimit = 2
write-host ('Throttled to ' + $throttleLimit + ' concurrent threads')

$iss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
$Pool = [runspacefactory]::CreateRunspacePool(1,$throttleLimit,$iss,$Host)
$Pool.Open()
#endregion

#This works because the console color is set at the time output occurs
$OrigfC = $host.UI.RawUI.ForegroundColor
$host.UI.RawUI.ForegroundColor = 'red'
write-host 'THIS IS RED TEXT!'
start-sleep 2
$host.UI.RawUI.ForegroundColor = $OrigfC

#define code to run off the main thread
$scriptBlock = {
$nl = ([Environment]::NewLine.Chars(0)+[Environment]::NewLine.Chars(1))

#This does not work because output won't occur until after color has been reset
$OrigfC = $host.UI.RawUI.ForegroundColor
$host.UI.RawUI.ForegroundColor = 'yellow'
write-output ($nl + ' TEST: ' + $args[0])
Write-Output (' Some write-output: ' + $args[0])
Start-Sleep 1
write-host (' Some write-host: ' + $args[0]) -ForegroundColor Cyan # notice write-host occurs immediately
Start-Sleep 1
$host.UI.RawUI.ForegroundColor = $OrigfC
}

#Start new runspaces
$threads = @()
$handles = @(for($x = 1; $x -le $iterations; $x++)
{
$powerShell = [PowerShell]::Create().AddScript($scriptBlock).AddParameters(@($x))
$powershell.RunspacePool = $Pool
$powerShell.BeginInvoke()
$threads += $powerShell
})

#Wait for threads to complete
$completedCount = 0
$completed = ($handles | where-object {$_.IsCompleted -eq $true}).count
while($handles.IsCompleted.Contains($false))
{
if($completedCount -ne ($handles | where-object {$_.IsCompleted -eq $true}).count)
{
$completedCount = ($handles | where-object {$_.IsCompleted -eq $true}).count
write-host ('Threads Completed: ' + $completedCount + ' of ' + $iterations)
}
write-host '.' -nonewline
Start-Sleep 1
}
write-host ('Threads Completed: ' + ($handles | where-object {$_.IsCompleted -eq $true}).count + ' of ' + $iterations)

#output from threads
for($z = 0; $z -lt $handles.Count; $z++)
{
$threads[$z].EndInvoke($handles[$z]) #causes output
$threads[$z].Dispose()
$handles[$z] = $null
}

$Pool.Dispose()

下面是输出,除非指定,否则输出为灰色:
我的目标是能够将表示“Some write-output:X”的行设置为一种颜色,而将“TEST:X”的行设置为另一种颜色。有想法吗?请注意,我正在从Powershell提示符运行。如果在ISE中运行,您将得到不同的结果。
Throttled to 2 concurrent threads
THIS IS RED TEXT! #Outputs in Red
. Some write-host: 1 #Outputs in Cyan
Some write-host: 2 #Outputs in Cyan
.Threads Completed: 2 of 5 #Outputs in Yellow
. Some write-host: 3 #Outputs in Cyan
Some write-host: 4 #Outputs in Cyan
.Threads Completed: 4 of 5 #Outputs in Yellow
. Some write-host: 5 #Outputs in Cyan
.Threads Completed: 5 of 5

TEST: 1
Some write-output: 1

TEST: 2
Some write-output: 2

TEST: 3
Some write-output: 3

TEST: 4
Some write-output: 4

TEST: 5
Some write-output: 5

编辑:添加另一个示例来解决Mjolinor的答案。 M,您是正确的,我可以通过工作 session ;我在上面简化了我的示例。请考虑下面的示例,在该示例中,我正在向工作发送功能。如果在下面将这一行(if(1 -ne 1){MyFunc -ses $ args [0]})注释掉,它将运行。如果该行未被注释掉,则即使无法命中MyFunc调用, session (类型System.Management.Automation.Runspaces.PSSession)也将转换为Deserialized.System.Management.Automation.Runspaces.PSSession类型。我无法弄清楚这一点,所以我开始转向运行空间。您是否认为有面向工作的解决方案?
cls
$ses = New-PSSession -ComputerName XXXX
Write-Host ('Outside job: '+$ses.GetType())

$func = {
function MyFunc {
param([parameter(Mandatory=$true)][PSSession]$ses)
Write-Host ('Inside fcn: '+$ses.GetType())
}
}

$scriptBlock = {
Write-Host ('Inside job: '+$args[0].GetType())
if(1 -ne 1){MyFunc -ses $args[0]}
}

Start-Job -InitializationScript $func -ScriptBlock $scriptBlock -Args @($ses) | Out-Null
While (Get-Job -State "Running") { }
Get-Job | Receive-Job
Remove-Job *
Remove-PSSession -Session $ses

最佳答案

我不太理解不能将PSSession传递给工作的说法。您可以同时使用-Session和-AsJob参数运行Invoke-Command,以针对该 session 的作业创建。

就着色难题而言,您是否考虑过将Verbose或Debug流用于要成为其他颜色的输出? Powershell会根据其来源自动将其设置为其他颜色。

关于multithreading - Powershell运行空间和颜色输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15886040/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com