我想使用vSphere PowerCLI获取所有虚拟机,并输出一些其他信息。但是我没有使输出正常工作。
我已经尝试将其作为控制台输出,但是后来却没有获得带有操作系统和IP地址的名称
$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
}
到目前为止,这是我的“最佳方法”。
我的结果应类似于
SomeVMname SomeOS SomeIP
但是由于我没有正确处理自定义对象,我到目前为止只得到了总String或错误的Length
:
因此,如果有人可以通过控制台输出或我可以导出到csv的对象来帮助我,我将对此感到非常满意
答案 0 :(得分:2)
您已经非常接近完成这项工作了。您只需要在$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
AVShalom's helpful answer暗示了一些有关处理IPAddress
属性和删除不必要的命令(即Get-VMGuest
)以实现所需目标的想法。他使用快捷方式创建对象$row
,该对象将保存虚拟机属性。但是,使用数组替换和附加技术$Report += Row
会带来固有的效率低下,因为每次循环迭代时都会创建一个更大的新数组对象。对于较小的数据集,这可能并不重要,但是对于较大的数据集,这可能会很重要。
一旦创建[PSCustomObject]
,就可以在属性中编辑该值,只要该对象没有被破坏和/或那些属性定义保留在该对象上即可。这意味着您可以在循环的每次迭代期间为相同属性使用所有新值(如果需要)。我添加了[ordered]
属性,以使$object
属性顺序在您的输出中保持一致。
我添加了$Output
变量以在循环的每次迭代期间存储$Object
的值。 $Output
成为具有您要跟踪的三个属性的对象的数组。现在,您的Export-Csv
会将这些属性值转换为CSV文件的字符串。
我删除了Get-VMGuest
命令,因为$name
变量是一个对象,其中包含您已经需要的所有信息。 Guest
属性提供Get-VMGuest
提供的信息。
您可以将IPAddress
的值强制转换为字符串,因为由于该属性是一个数组,因此有时可能会有多个IP。您可以选择仅获取索引值($Name.Guest.IPAddress[0]
);但是,您必须注意这一点,因为所需的IP地址可能在另一个索引中。 [string]
强制转换将使用空格定界符返回该属性的所有值。我改用-join
运算符,并使用空格定界符。 IPAddress
也可能包含IPv6地址。我只想捕获IPv4地址,所以我使用了Regex匹配,例如$Name.Guest.IPAddress -match "\."
,与文字.
字符匹配。您可以结合多种技术来获取所需的数据。
请考虑以下对象和示例:
$name.guest
IPAddress OSFullName
--------- ----------
{1.1.1.1, 2.2.2.2, fe80::ffff:ffff:ffff:ffff} Windows StackOverflow
$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"
答案 1 :(得分:0)
您不需要使用Get-VMGuest
来获取OS / IP信息,您已经使用Get-VM
属性成员将其与Guest
一起使用了:
应该那样简单:
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
}
[0]
,您可以使用正则表达式来匹配特定的模式