2013-04-08 4 views
1

짧은 문제 설명 :
파워 쉘 실행 영역 및 컬러 출력

내가 내 스크립트를 생성합니다 추가 파워 쉘의 실행 영역에서 비 산재 출력이 필요합니다. 출력에서 개별 라인의 색상을 설정할 수 있어야합니다.

긴 문제 설명 :

나는 여러 원격 서버 공급 업체 응용 프로그램 업데이트를 배포하는 스크립트를 썼다. 원래 스크립트는 한 번에 하나의 업데이트 만 배포하기위한 것이었지만 이제는 여러 업데이트를 대화식으로 처리해야한다는 새로운 요구 사항이 있습니다. 그래서 스크립트를 다시 작성하여 모든 서버에서 세션을 열고 초기화 한 다음 사용자가 입력 한 runspace가 초기화 된 각 세션에 대해 작성되고 배포 작업이 완료 될 때까지 runspaces를 사용하도록 스크립트를 다시 작성했습니다. 이전에는 작업을 사용했지만 PSSession을 작업에 전달할 수 없기 때문에 실행 영역으로 이동해야했습니다.

이제 스크립트가 제대로 작동하지만 결과가 좋지 않습니다. Receive-Job을 호출하고 모든 출력을 스레드별로 그룹화 할 수 있기 때문에 작업 버전의 출력이 좋았습니다. 또한 쓰기 호스트를 사용하여 컬러 응답 (예 : 업데이트가 적용되지 않으면 빨간색 텍스트)을 허용하는 출력을 기록 할 수 있습니다. 스레드의 출력을 그룹화하기 위해 작업의 내 runspace 버전을 얻을 수 있었지만 쓰기 출력 만 사용했습니다. write-host 출력을 사용하면 즉시 발생하여 중간에 출력되는 것을 받아 들일 수 없습니다. 불행히도 write-output은 컬러 출력을 허용하지 않습니다. $ host.UI.RawUI.ForegroundColor를 설정해도 색상이 설정된 시점에 출력이 발생하지 않으면 효과가 나타나지 않으므로 작동하지 않습니다. 출력이 끝날 때까지 발생하지 않기 때문에 $ 호스트 설정은 더 이상 작동하지 않습니다. 다음은

내 불황을 설명하는 빠른 데모 스크립트입니다

#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() 

출력을 지정하지 않는 출력은 다음과 같습니다 은 회색에 있습니다
내 목표는 라인을 얻을 수있을 것입니다 "일부 쓰기 출력 : 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, 너는 맞다. 나는 직업을 직업에 넘겨 줄 수있다; 위의 예를 지나치게 단순화했습니다. 아래의 예제에서 내가 작업에 기능을 전송하는 위치를 고려해보십시오. 이 행 (if (1 -ne 1) {MyFunc -ses $ args [0]})이 아래 주석 처리되면 실행됩니다. 해당 줄이 주석 처리되지 않은 경우 MyFunc 호출에 적중 될 수 없더라도 세션 (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 

답변

1

PSSession을 작업에 전달할 수 없다는 사실을 이해하지 못합니다. 세션을 대상으로하는 작업에서 작성하는 -Session 및 -AsJob 매개 변수로 Invoke-Command를 실행할 수 있습니다.

컬러링 수수께끼와 관련하여 다른 색상으로 만들고 싶은 출력에 Verbose 또는 Debug 스트림을 사용 해본 적이 있습니까? Powershell은 스트림의 출현에 따라 자동으로 다른 색상으로 만들어야합니다.

+0

필자는 내 작업에서 기능과 관련하여 겪고있는 문제점을 보여주는 추가 예제를 추가했습니다. 이것을 봐주세요. –

+1

-session 및 -asjob 매개 변수와 함께 invoke-command를 사용해 보셨습니까? Start-Job은 로컬 시스템에 백그라운드 작업을 생성합니다. 원격 시스템에서 스크립트를 실행하기 위해 로컬 백그라운드 작업을 만드는 이유를 이해할 수 없습니다. 작업으로 원격 시스템에서 스크립트를 호출하기 만하면됩니다. – mjolinor

+0

로컬 작업을 시작한 다음 작업 내에서 invoke-command를 호출합니다. 배포 성공에 따라 필자는 invoke 명령을 사용하여 로그 파일의 내용을 로컬 작업에 다시 표시 할 수 있습니다. 그런 다음 로컬 작업은 로컬 로그 파일을 만들 수 있으므로 사용자가 여러 서버에 로그인하여 오류 로그를 검색 할 필요가 없습니다. invoke-command를 사용하여 동일한 결과를 얻으 려합니다. –