이 샘플 스크립트를 복사하여 붙여넣고 환경에 필요한 대로 수정합니다.
<# . 시놉시스 보안 부팅 롤아웃 오케스트레이터의 현재 상태 표시합니다.
.DESCRIPTION 출시 진행률에 대한 실시간 가시성을 제공합니다. - 현재 웨이브 번호 및 대상 디바이스 - 디바이스 업데이트 및 보류 중 - 주의가 필요한 차단된 버킷 - 최근 활동 로그 - 대시보드 링크 언제든지 실행하여 롤아웃이 어떻게 진행되는지 확인합니다.
.PARAMETER ReportBasePath 오케스트레이터에서 사용하는 보고서/상태 디렉터리의 경로
.PARAMETER ShowLog 최근 로그 항목 표시(마지막 50줄)
.PARAMETER ShowBlocked 차단된 버킷의 세부 정보 표시
.PARAMETER ShowWaves 디바이스 수를 사용하여 웨이브 기록 표시
.PARAMETER Watch N초마다 상태 지속적으로 새로 고침
.PARAMETER OpenDashboard 브라우저에서 최신 HTML dashboard 엽니다.
.EXAMPLE .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath "C:\SecureBootReports"
.EXAMPLE .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath "C:\SecureBootReports" -Watch 30
.EXAMPLE .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath "C:\SecureBootReports" -OpenDashboard #>
[CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ReportBasePath, [Parameter(Mandatory = $false)] [switch]$ShowLog [Parameter(Mandatory = $false)] [switch]$ShowBlocked, [Parameter(Mandatory = $false)] [switch]$ShowWaves, [Parameter(Mandatory = $false)] [int]$Watch = 0, [Parameter(Mandatory = $false)] [switch]$OpenDashboard )
$ErrorActionPreference = "Stop" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "배포 및 모니터링 샘플"
# Note: This script has no dependencies on other scripts. # 전체 도구 집합의 경우 다음에서 다운로드합니다. $DownloadUrl -> $DownloadSubPage
# ============================================================================ # 도우미 함수 # ============================================================================
function ConvertTo-Hashtable { param([Parameter(ValueFromPipeline = $true)]$InputObject) 프로세스 { if ($null -eq $InputObject) { return @{} } if ($InputObject -is [System.Collections.IDictionary]) { return $InputObject } if ($InputObject -is [PSCustomObject]) { $hash = @{} foreach($InputObject.PSObject.Properties의 $prop) { $hash[$prop. Name] = ConvertTo-Hashtable $prop. 값 } return $hash } if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) { return @($InputObject | ForEach-Object { ConvertTo-Hashtable $_ }) } return $InputObject } }
function Show-Status { $stateDir = Join-Path $ReportBasePath "RolloutState" $rolloutStatePath = Join-Path $stateDir "RolloutState.json" $blockedBucketsPath = Join-Path $stateDir "BlockedBuckets.json" Clear-Host Write-Host "" Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host "보안 부팅 롤아웃 상태" -ForegroundColor Cyan Write-Host " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Gray Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host "" # 오케스트레이터 작업이 실행 중인지 확인 $task = Get-ScheduledTask -TaskName "SecureBoot-Rollout-Orchestrator" -ErrorAction SilentlyContinue if ($task) { $taskState = $task. 상태 $color = if ($taskState -eq "Running") { "Green" } elseif ($taskState -eq "Ready") { "Yellow" } else { "Red" } Write-Host "예약된 작업: " -NoNewline Write-Host $taskState -ForegroundColor $color } else { Write-Host "예약된 작업: " -NoNewline Write-Host "설치되지 않음" -ForegroundColor 회색 } # 부하 롤아웃 상태 if (-not (Test-Path $rolloutStatePath)) { Write-Host "" Write-Host "롤아웃 상태를 찾을 수 없습니다. 오케스트레이터가 아직 시작되지 않았을 수 있습니다." -ForegroundColor 노란색 Write-Host "상태 경로: $rolloutStatePath" -ForegroundColor 회색 반환 } $state = Get-Content $rolloutStatePath -Raw | ConvertFrom-Json | ConvertTo-Hashtable Write-Host "" Write-Host "롤아웃 진행률" -ForegroundColor Yellow Write-Host("-" * 40) $상태 = $state. 상태 $statusColor = 스위치($상태) { "Completed" { "Green" } "InProgress" { "Cyan" } "NotStarted" { "Gray" } default { "White" } } Write-Host "상태: " -NoNewline Write-Host $상태 -ForegroundColor $statusColor Write-Host "현재 웨이브: $($state. CurrentWave)" Write-Host "총 대상: $($state. TotalDevicesTargeted)" Write-Host "업데이트된 총액: $($state. TotalDevicesUpdated)" if($state. StartedAt) { Write-Host "시작: $($state. StartedAt)" } if($state. LastAggregation) { Write-Host "마지막 확인: $($state. LastAggregation)" } if($state. CompletedAt) { Write-Host "완료됨: $($state. CompletedAt)" -ForegroundColor Green } # 진행률 표시줄 표시 if($state. TotalDevicesTargeted -gt 0) { $pct = if($state. TotalDevicesUpdated -및 $state. TotalDevicesTargeted) { [math]::Round(($state. TotalDevicesUpdated/$state. TotalDevicesTargeted) * 100, 1) } else { 0 } Write-Host "" Write-Host "Progress: " -NoNewline $barWidth = 40 $filled = [math]::Floor($barWidth * $pct/ 100) Write-Host "[" -NoNewline Write-Host("█" * $filled) -ForegroundColor Green -NoNewline Write-Host ("░" * ($barWidth - $filled)) -ForegroundColor DarkGray -NoNewline Write-Host "] $pct%" } # 차단된 버킷 요약 if (Test-Path $blockedBucketsPath) { $blocked = Get-Content $blockedBucketsPath -Raw | ConvertFrom-Json | ConvertTo-Hashtable if($blocked. Count -gt 0) { Write-Host "" Write-Host "차단된 버킷: " -NoNewline -ForegroundColor Red Write-Host "$($blocked. Count) 버킷에 주의가 필요합니다." -ForegroundColor Red if ($ShowBlocked) { Write-Host "" foreach($blocked $key. 키) { $info = $blocked[$key] Write-Host " • $key" -ForegroundColor Red Write-Host " 이유: $($info. Reason)" -ForegroundColor Gray Write-Host " 디바이스: $($info. FailedDevice)" -ForegroundColor Gray Write-Host " 이후: $($info. BlockedAt)" -ForegroundColor Gray } } else { Write-Host "자세한 내용은 -ShowBlocked를 사용하여 실행" -ForegroundColor Gray } } } # 웨이브 기록 if($ShowWaves 및 $state. WaveHistory -and $state. WaveHistory.Count -gt 0) { Write-Host "" Write-Host "WAVE HISTORY" -ForegroundColor Yellow Write-Host ("-" * 40) foreach($state $wave. WaveHistory) { Write-Host "웨이브 $($wave. WaveNumber): " -NoNewline -ForegroundColor Cyan Write-Host "$($wave. DeviceCount) 디바이스" -NoNewline Write-Host " - $($wave. StartedAt)" -ForegroundColor Gray } } # 최신 dashboard $latestAggregation = Get-ChildItem -Path $ReportBasePath -Directory -Filter "Aggregation_*" -ErrorAction SilentlyContinue | Sort-Object 이름 -내림차순 | Select-Object -First 1 if ($latestAggregation) { $dashboard = Get-ChildItem -Path $latestAggregation.FullName -Filter "*Dashboard*.html" -ErrorAction SilentlyContinue | Select-Object -First 1 if ($dashboard) { Write-Host "" Write-Host "최신 대시보드" -ForegroundColor 노란색 $dashboard Write-Host. FullName -ForegroundColor Gray if ($OpenDashboard) { $dashboard Start-Process. Fullname } } } # 최근 로그 if ($ShowLog) { $logFile = Get-ChildItem -Path $stateDir -Filter "Orchestrator_*.log" -ErrorAction SilentlyContinue | Sort-Object 이름 -내림차순 | Select-Object -First 1 if ($logFile) { Write-Host "" Write-Host "최근 로그" -ForegroundColor 노란색 Write-Host("-" * 40) Get-Content $logFile.FullName -Tail 20 | ForEach-Object { if ($_ -match '\[ERROR\]') { Write-Host $_ -ForegroundColor Red } elseif ($_ -match '\[WARN\]') { Write-Host $_ -ForegroundColor 노란색 } elseif ($_ -match '\[OK\]') { Write-Host $_ -ForegroundColor Green } elseif ($_ -match '\[WAVE\]') { Write-Host $_ -ForegroundColor Cyan } else { Write-Host $_ -ForegroundColor Gray } } } } Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray if (-not $ShowLog -또는 -not $ShowWaves -or -not $ShowBlocked) { Write-Host "옵션: -ShowLog | -ShowWaves | -ShowBlocked | -OpenDashboard | -Watch 30" -ForegroundColor DarkGray } }
# ============================================================================ # MAIN # ============================================================================
if (-not (Test-Path $ReportBasePath)) { Write-Host "보고서 경로를 찾을 수 없음: $ReportBasePath" -ForegroundColor Red 종료 1 }
if ($Watch -gt 0) { Write-Host "$Watch 초마다 상태. Ctrl+C를 눌러 중지합니다." -ForegroundColor Cyan while ($true) { Show-Status Start-Sleep -초 $Watch } } else { Show-Status }