【问题标题】:Displaying Column Headers Once in Output Report在输出报告中显示一次列标题
【发布时间】:2020-12-12 22:11:03
【问题描述】:

我正在编写一个脚本来使用 PowerCLI 审核我公司虚拟环境中的磁盘分区类型。到目前为止,我已经得到了这段代码:

$report = @()

$VMs = (Get-VM).where{$_.PowerState -eq 'PoweredOn' -and $_.Guest.OSFullName -match 'Windows'}

foreach ($VM in $VMs){
    $vmName = $VM.Name
    $output = Invoke-VMScript -ScriptText @'
      Get-Disk | 
        select @{ l="ComputerName"; e={ $env:COMPUTERNAME } },
               Number, 
               @{ name='Size'; expr={[int]($_.Size/1GB)} },
               PartitionStyle
'@ -VM $vmName -GuestUser $Username -GuestPassword $Password

    $output.ScriptOutput #printing each for testing
    $report += $output.ScriptOutput
}
$report | FT -AutoSize

这将产生如下所示的输出:

ComputerName Number Size PartitionStyle
VMNAME1 0 100 MBR
VMNAME1 1 20 GPT
VMNAME1 2 20 MBR
ComputerName Number Size PartitionStyle
VMNAME2 0 100 MBR
VMNAME2 1 20 GPT

我面临的问题是输出报告的列标题为每个 VM 重复。我该如何解决这个问题,只显示一次列标题,如下所示:

ComputerName Number Size PartitionStyle
VMNAME1 0 100 MBR
VMNAME1 1 20 GPT
VMNAME1 2 20 MBR
VMNAME2 0 100 MBR
VMNAME2 1 20 GPT

关于如何做到这一点的任何想法?我是 powershell 新手,所以我不知道该怎么做。

【问题讨论】:

  • 删除或注释掉$output.ScriptOutput #printing each for testing这一行。使用+- 连接到数组也很昂贵。
  • @Theo 删除对它没有影响

标签: powershell powercli


【解决方案1】:

由于 ScriptOutput 的输出是字符串,你必须自己解析它。相反,我建议将其转换为适合作为文本传递的格式,例如 CSV。

$VMs = (Get-VM).where{$_.PowerState -eq 'PoweredOn' -and $_.Guest.OSFullName -match 'Windows'}

$report = foreach ($VM in $VMs){
    $vmName = $VM.name
    $output = Invoke-VMScript -ScriptText @'
      Get-Disk | 
        select @{ l="ComputerName"; e={ $env:COMPUTERNAME } },
               Number, 
               @{ name='Size'; expr={[int]($_.Size/1GB)} },
               PartitionStyle | ConvertTo-Csv
'@ -VM $vmName -GuestUser $Username -GuestPassword $Password

    $output.ScriptOutput | ConvertFrom-Csv
}

$report | FT -AutoSize

此外,正如 Theo 评论的那样,+= 可能非常昂贵,而且几乎总是不必要的。如此处所示,您可以简单地将 foreach 的输出直接收集到变量中。

编辑

由于任何额外的输出(例如错误)与您想要的数据一起被捕获,它可能会导致您提到的额外空行。我能够克服这个问题的一种方法是检查列标题是否存在,然后删除之前的任何垃圾。

$VMs = (Get-VM).where{$_.PowerState -eq 'PoweredOn' -and $_.Guest.OSFullName -match 'Windows'}

$report = foreach ($VM in $VMs){
    $output = Invoke-VMScript -ScriptText @'
        Get-Disk | Foreach-Object{
            [PSCustomObject]@{
                ComputerName   = $env:COMPUTERNAME
                Number         = $_.number
                Size           = [int]($_.size/1GB)
                PartitionStyle = $_.PartitionStyle
            }
        } | ConvertTo-Csv -NoTypeInformation

'@ -VM $vm.Name -GuestUser $Username -GuestPassword $Password

    if($output.ScriptOutput -match 'PartitionStyle')
    {
        $output.ScriptOutput -replace '(?s)^.+(?="Com)' | ConvertFrom-Csv
    }
}

$report | FT -AutoSize

【讨论】:

  • 这会产生几乎空白的输出,除了在尝试连接到某些 VM 时出现一些权限被拒绝错误 - 请参阅 here
  • 那是一个单独的问题
  • 是的,我知道,不过目前并不真正关心这些错误。将分别调查他们中的每一个。只是不知道为什么输出会是空白的......
  • 如果有任何其他输出,包括包含错误在内的所有输出。我会一个一个地运行每个虚拟机,看看你遇到了什么错误。
  • 检查我的编辑。一些额外的步骤应该可以帮助您获得所需的输出。如果您可以选择切换到 Invoke-Command,为了您自己,请这样做。将脚本作为字符串发送,并将所有输出作为字符串返回,这就是 powershell 用来拯救我们的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
  • 2019-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多