所有 VM PowerCLI 信息输出/控制台和自定义对象均无法正常工作

All VMs PowerCLI Info output /Console and Custom Object Not Working Properly

我想使用 vSphere PowerCLI 获取我们所有的 VM,并在 ose 中输出一些附加信息。但是我没有让输出正常工作。

我已经尝试将它作为控制台输出,但后来我没有得到带有 os 和 IPAddress

的名称
$Object = New-Object PSObject -Property @{
    Name = $name
    OS = $info.OSFullName
    IP = $info.IPAddress
    }

Connect-VIServer -Server VMServer -Credential admin -Password ASecretPWnoOneKnows

$allnames = Get-VM

foreach($name in $allnames)
{
    $info = Get-VMGuest $name | select OSFullName, IPAddress
    Add-Member -InputObject $Object
}

到目前为止,这是我的"best approach"。

我的结果应该像

SomeVMname SomeOS SomeIP

但到目前为止我只得到了总字符串的 Length 或错误,因为我没有正确处理自定义对象:

因此,如果有人可以帮助我,控制台输出或我也可以导出到 csv 的对象,我会非常高兴

您已经非常接近完成这项工作了。您只需将 $object 创建和检索移动到 ForEach 循环中。

Connect-VIServer -Server VMServer -Credential admin -Password ASecretPWnoOneKnows
$allnames = Get-VM

$Output = foreach($name in $allnames)
{
  $Object = [PSCustomObject][ordered]@{
    Name=$name.Name
    OS=$name.Guest.OSFullName
    IP=$name.Guest.IPAddress -match "\." -join " "
  }
  $Object
}
$Output # To output to the console
$Output | Export-Csv -path "file.csv" -NoTypeInformaton # Csv output

暗示了一些关于处理 IPAddress 属性 和删除不必要的命令的想法,即 Get-VMGuest,以达到预期的目标。他使用快捷方式创建将保存虚拟机属性的对象 $row。但是,使用数组替换和添加技术 $Report += Row 存在固有的低效率,因为每次循环迭代时都会创建一个更大的新数组对象。对于较小的数据集,这可能无关紧要,但对于较大的数据集,这可能很重要。

创建 [PSCustomObject] 后,只要该对象未被销毁,您就可以编辑属性中的值 and/or 这些 属性 定义保留在对象上。这意味着您可以在循环的每次迭代期间为 相同的属性 获得所有新值(如果您愿意)。我添加了 [ordered] 属性,以便 $object 属性 顺序在您的输出中保持一致。

我添加了 $Output 变量以在循环的每次迭代期间存储 $Object 的值。 $Output 成为具有您要跟踪的三个属性的对象数组。现在,您的 Export-Csv 会将这些 属性 值转换为 CSV 文件的字符串。

我删除了 Get-VMGuest 命令,因为 $name 变量是一个包含您已经需要的所有信息的对象。 Guest 属性 提供 Get-VMGuest 提供的信息。

您可以将 IPAddress 值转换为字符串,因为有时会有多个 IP,因为 属性 是一个数组。您可以选择只获取一个索引值 ($Name.Guest.IPAddress[0]);但是,您必须小心,因为您想要的 IP 地址可能在另一个索引中。 [string] 转换将 return 使用 space 分隔符的 属性 的所有值。我改用了 -join 运算符并使用了 space 定界符。 IPAddress 也可能包含 IPv6 地址。我只想捕获 IPv4 地址,所以我使用了正则表达式匹配,例如$Name.Guest.IPAddress -match "\.",匹配文字 . 字符。您可以结合多种技术来获取所需的数据。

考虑以下对象和示例:

$name.guest

IPAddress                                     OSFullName
---------                                     ----------
{1.1.1.1, 2.2.2.2, fe80::ffff:ffff:ffff:ffff} Windows Whosebug

$name.guest.IPAddress # Retrieves all IPs
1.1.1.1
2.2.2.2
fe80::ffff:ffff:ffff:ffff

$name.guest.IPAddress[0] # Retrieves the first IP in the array
1.1.1.1

$name.guest.IPAddress -match "\." # Retrieves all IPv4 IPs
1.1.1.1
2.2.2.2

$name.guest.IPAddress -match "\." -join " " # Retrieves all IPv4 separated by space
1.1.1.1 2.2.2.2

根据您的代码结构方式,您似乎正在尝试创建其值是通过引用而不是通过值的属性。为了进一步解释,您似乎希望 $Object 的 属性 值随着 $info 属性 值自动更改 而无需更新显式赋值。我不知道那是否是你的意图,但我相信这会增加你想要完成的事情的复杂性。我没有为您的代码执行此操作。每次循环迭代时,我都会明确设置 $Object 属性 值。

我也没有看到你的Export-Csv命令;但是,您描述了 Length 属性 的输出。当您 Export-Csv[string] 对象作为输入对象时,就会发生这种情况。由于 Export-Csv 的目的是将 属性 值转换为字符串,因此常规字符串的唯一 属性 值是 Length。所以这是可以预料的。您可以在下面看到此行为:

$str = "this is a string"
($str | Get-Member).where({$_.MemberType -eq "Property"})


   TypeName: System.String

Name   MemberType Definition
----   ---------- ----------
Length Property   int Length {get;}
$str | ConvertTo-Csv
#TYPE System.String
"Length"
"16"

您不需要使用 Get-VMGuest 来获取 OS/IP 信息,您已经使用 Guest 属性 成员通过 Get-VM 获得了它:

应该就这么简单:

Connect-VIServer -Server VMServer -Credential admin -Password ASecretPWnoOneKnows

$Report = @()
$VMs = Get-VM
foreach ($vm in $VMs)
{
$row = "" | Select Name,OSFullName,IP
$row.Name = $vm.name
$row.OSFullName = $vm.Guest.OSFullName
$row.IP = $vm.Guest.IPAddress[0]
$Report += $row
}
  • 请注意,IP 地址可能包含多个 IP,例如IPV4/V6,例子中我收集了第一个[0]你可以使用正则表达式来匹配特定的模式