如何从非集群节点远程捕获集群信息
How to Capture Cluster info Remotely from a non-Clustered Node
几天来我一直在努力解决这个问题,但我就是想不出最好的方法。我有一个脚本,我在其中收集了一堆数据并将其输出到一个 html 文件(使用 PSWriteHTML 模块,这是最后的 New-HTMLTable 来自的地方)。
随着时间的推移,我将脚本拼凑在一起,这样我就可以同时从多个服务器收集数据,而且在大多数情况下,一切都很好。由于我已将数据添加到脚本以收集新信息,所以有几个部分我无法远程正常工作。我知道零碎的方法给我留下了一些冗余代码,但我只是想在我再次重写它以清理它之前让它全部正常工作,所以我对它的当前状态表示歉意。
当我 运行 来自 Windows 集群中的服务器的脚本时,以下代码工作得很好,但我希望在任何服务器上运行,不一定是集群节点。
这是本节的原始代码:
try
{
$ClusterIPInfo = Invoke-command -computer $Computer {
Get-Cluster | Get-ClusterResource | %{
$_ | select Name,
@{ Name = "Address"; Expression = { $_ | Get-ClusterParameter -Name Address -ErrorAction SilentlyContinue | select -ExpandProperty Value } },
@{ Name = "SubnetMask"; Expression = { $_ | Get-ClusterParameter -Name SubnetMask -ErrorAction SilentlyContinue | select -ExpandProperty Value } }
}
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ClusterResourceInfo = Invoke-command -computer $Computer {
Get-ClusterResource | Select Cluster, Name, State, ResourceType, OwnerGroup, OwnerNode, ID, IsCoreResource, IsNetworkClassResource, IsStorageClassResource | Sort-Object -Property OwnerGroup, Name
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ResourceInfo = @()
foreach ($rec in $ClusterResourceInfo)
{
$Owner = (Get-ClusterResource | Sort-Object -Property OwnerGroup, Name | Get-ClusterOwnerNode | %{
$_ | select @{ Name = "Name"; Expression = { $_.ClusterObject } },
@{ Name = "PossibleOwners"; Expression = { $_.OwnerNodes } }
} | Where { $_.Name -eq $rec.Name }).PossibleOwners
$Dependency = (Get-ClusterResource | Sort-Object -Property OwnerGroup, Name | Get-ClusterResourceDependency | %{
$_ | select @{ Name = "Name"; Expression = { $_.Resource } },
@{ Name = "Dependency"; Expression = { $_ | Select-Object -ExpandProperty "DependencyExpression" } }
} | Where { $_.Name -eq $rec.Name }).Dependency
$address = ($ClusterIPInfo | Where { $_.Name -eq $rec.Name }).Address
$subnetmask = ($ClusterIPInfo | Where { $_.Name -eq $rec.Name }).SubnetMask
$recObj = New-Object PSObject
$recObj | Add-Member NoteProperty -Name "Cluster" -Value $rec.Cluster
$recObj | Add-Member NoteProperty -Name "Name" -Value $rec.Name
$recObj | Add-Member NoteProperty -Name "State" -Value $rec.State
$recObj | Add-Member NoteProperty -Name "Resource Type" -Value $rec.ResourceType
$recObj | Add-Member NoteProperty -Name "Owner Group" -Value $rec.OwnerGroup
$recObj | Add-Member NoteProperty -Name "Owner Node" -Value $rec.OwnerNode
$recObj | Add-Member NoteProperty -Name "Possible Owners" -Value $Owner
$recObj | Add-Member NoteProperty -Name "Dependency" -Value $Dependency
$recObj | Add-Member NoteProperty -Name "IP Address" -Value $address
$recObj | Add-Member NoteProperty -Name "Subnet Mask" -Value $subnetmask
$recObj | Add-Member NoteProperty -Name "Is Core Resource" -Value $rec.IsCoreResource
$recObj | Add-Member NoteProperty -Name "Is Network Resource" -Value $rec.IsNetworkClassResource
$recObj | Add-Member NoteProperty -Name "Is Storage Resource" -Value $rec.IsStorageClassResource
$ResourceInfo += $recObj
}
New-HTMLTable -DataTable $ResourceInfo -HideFooter -HideButtons -DisableSearch
远程无法正常工作的部分是 Dependency 和 PossibleOwners。我知道它不起作用的原因是因为当服务器 运行ning 脚本不是集群节点时,它无法识别 Foreach 循环 Get-ClusterResource 下的命令。但我只是想不出如何使它们从 Foreach 循环中正确传递,但仍然使用来自 $ClusterResourceInfo 的信息。
我用一百种不同的方式重写了这个,即用一个大的 Get-Cluster 变量创建一个 Invoke-command(无法让它捕获 Dependency/PossOwners,总是 $null ),将 Dependency 和 PossOwners 拆分为它们自己单独的 Invoke-Command(我能做的最好的事情是显示 System.Object[],或者当我确实显示它时,它捕获了所有的所有依赖项对象并显示在每一行上,而不是正确地拆分它)。
我已经尝试了所有我能想到或在网上找到的方法,但就是无法让它在远程正常工作。
上面的原始代码是这样输出的(这是我想要的,但我只是想修复它以便它可以远程工作):
我迫切希望得到一些智慧或指导,让我走上正轨。我尝试了很多方法,但从来没有完全得到它需要的地方,所以非常感谢和欢迎任何帮助。谢谢
我可以提出一些建议。
“Get-ClusterResource”cmdlet 失败,因为它未安装在服务器上。
您可以尝试使用 Import-Module 加载故障转移集群模块,如果失败(在非集群节点上),您可以使用以下 PowerShell 命令为 Windows PowerShell 功能添加故障转移集群模块:
添加-Windows功能 RSAT-Clustering-PowerShell
您可以尝试使用 WMI 连接到托管资源的远程集群节点吗?
您有足够的资源信息,可以编写经过筛选的 WMI 查询。
所以零碎的方法让我遇到了麻烦。在尝试将事物合并在一起时,我一直在破坏它(主要是因为我认为 %{} 加倍了)。因此,我没有合并,而是复制了已经按预期工作的部分。
最终这段代码运行良好:
$ClusterInfo = Invoke-command -computer $Computer {
Get-Cluster | Get-ClusterResource | %{
$_ | select Name,
@{ Name = "Address"; Expression = { $_ | Get-ClusterParameter -Name Address -ErrorAction SilentlyContinue | select -ExpandProperty Value } },
@{ Name = "SubnetMask"; Expression = { $_ | Get-ClusterParameter -Name SubnetMask -ErrorAction SilentlyContinue | select -ExpandProperty Value } },
@{ Name = "PossibleOwners"; Expression = { $_ | Get-ClusterOwnerNode | select OwnerNodes | select -ExpandProperty OwnerNodes } },
@{ Name = "Dependency"; Expression = { $_ | Get-ClusterResourceDependency | select -ExpandProperty "DependencyExpression" } }
}
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ClusterResourceInfo = Invoke-command -computer $Computer {
Get-ClusterResource | Select Cluster, Name, State, ResourceType, OwnerGroup, OwnerNode, IsCoreResource, IsNetworkClassResource, IsStorageClassResource | Sort-Object -Property OwnerGroup, Name
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ResourceInfo = @()
foreach ($rec in $ClusterResourceInfo)
{
$Owner = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).PossibleOwners
$Dependency = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).Dependency
$address = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).Address
$subnetmask = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).SubnetMask
$recObj = New-Object PSObject
$recObj | Add-Member NoteProperty -Name "Cluster" -Value $rec.Cluster
$recObj | Add-Member NoteProperty -Name "Name" -Value $rec.Name
$recObj | Add-Member NoteProperty -Name "State" -Value $rec.State
$recObj | Add-Member NoteProperty -Name "Resource Type" -Value $rec.ResourceType
$recObj | Add-Member NoteProperty -Name "Owner Group" -Value $rec.OwnerGroup
$recObj | Add-Member NoteProperty -Name "Owner Node" -Value $rec.OwnerNode
$recObj | Add-Member NoteProperty -Name "Possible Owners" -Value $Owner
$recObj | Add-Member NoteProperty -Name "Dependency" -Value $Dependency
$recObj | Add-Member NoteProperty -Name "IP Address" -Value $address
$recObj | Add-Member NoteProperty -Name "Subnet Mask" -Value $subnetmask
$recObj | Add-Member NoteProperty -Name "Is Core Resource" -Value $rec.IsCoreResource
$recObj | Add-Member NoteProperty -Name "Is Network Resource" -Value $rec.IsNetworkClassResource
$recObj | Add-Member NoteProperty -Name "Is Storage Resource" -Value $rec.IsStorageClassResource
$ResourceInfo += $recObj
}
New-HTMLTable -DataTable $ResourceInfo -HideFooter -HideButtons -DisableSearch
几天来我一直在努力解决这个问题,但我就是想不出最好的方法。我有一个脚本,我在其中收集了一堆数据并将其输出到一个 html 文件(使用 PSWriteHTML 模块,这是最后的 New-HTMLTable 来自的地方)。
随着时间的推移,我将脚本拼凑在一起,这样我就可以同时从多个服务器收集数据,而且在大多数情况下,一切都很好。由于我已将数据添加到脚本以收集新信息,所以有几个部分我无法远程正常工作。我知道零碎的方法给我留下了一些冗余代码,但我只是想在我再次重写它以清理它之前让它全部正常工作,所以我对它的当前状态表示歉意。
当我 运行 来自 Windows 集群中的服务器的脚本时,以下代码工作得很好,但我希望在任何服务器上运行,不一定是集群节点。
这是本节的原始代码:
try
{
$ClusterIPInfo = Invoke-command -computer $Computer {
Get-Cluster | Get-ClusterResource | %{
$_ | select Name,
@{ Name = "Address"; Expression = { $_ | Get-ClusterParameter -Name Address -ErrorAction SilentlyContinue | select -ExpandProperty Value } },
@{ Name = "SubnetMask"; Expression = { $_ | Get-ClusterParameter -Name SubnetMask -ErrorAction SilentlyContinue | select -ExpandProperty Value } }
}
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ClusterResourceInfo = Invoke-command -computer $Computer {
Get-ClusterResource | Select Cluster, Name, State, ResourceType, OwnerGroup, OwnerNode, ID, IsCoreResource, IsNetworkClassResource, IsStorageClassResource | Sort-Object -Property OwnerGroup, Name
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ResourceInfo = @()
foreach ($rec in $ClusterResourceInfo)
{
$Owner = (Get-ClusterResource | Sort-Object -Property OwnerGroup, Name | Get-ClusterOwnerNode | %{
$_ | select @{ Name = "Name"; Expression = { $_.ClusterObject } },
@{ Name = "PossibleOwners"; Expression = { $_.OwnerNodes } }
} | Where { $_.Name -eq $rec.Name }).PossibleOwners
$Dependency = (Get-ClusterResource | Sort-Object -Property OwnerGroup, Name | Get-ClusterResourceDependency | %{
$_ | select @{ Name = "Name"; Expression = { $_.Resource } },
@{ Name = "Dependency"; Expression = { $_ | Select-Object -ExpandProperty "DependencyExpression" } }
} | Where { $_.Name -eq $rec.Name }).Dependency
$address = ($ClusterIPInfo | Where { $_.Name -eq $rec.Name }).Address
$subnetmask = ($ClusterIPInfo | Where { $_.Name -eq $rec.Name }).SubnetMask
$recObj = New-Object PSObject
$recObj | Add-Member NoteProperty -Name "Cluster" -Value $rec.Cluster
$recObj | Add-Member NoteProperty -Name "Name" -Value $rec.Name
$recObj | Add-Member NoteProperty -Name "State" -Value $rec.State
$recObj | Add-Member NoteProperty -Name "Resource Type" -Value $rec.ResourceType
$recObj | Add-Member NoteProperty -Name "Owner Group" -Value $rec.OwnerGroup
$recObj | Add-Member NoteProperty -Name "Owner Node" -Value $rec.OwnerNode
$recObj | Add-Member NoteProperty -Name "Possible Owners" -Value $Owner
$recObj | Add-Member NoteProperty -Name "Dependency" -Value $Dependency
$recObj | Add-Member NoteProperty -Name "IP Address" -Value $address
$recObj | Add-Member NoteProperty -Name "Subnet Mask" -Value $subnetmask
$recObj | Add-Member NoteProperty -Name "Is Core Resource" -Value $rec.IsCoreResource
$recObj | Add-Member NoteProperty -Name "Is Network Resource" -Value $rec.IsNetworkClassResource
$recObj | Add-Member NoteProperty -Name "Is Storage Resource" -Value $rec.IsStorageClassResource
$ResourceInfo += $recObj
}
New-HTMLTable -DataTable $ResourceInfo -HideFooter -HideButtons -DisableSearch
远程无法正常工作的部分是 Dependency 和 PossibleOwners。我知道它不起作用的原因是因为当服务器 运行ning 脚本不是集群节点时,它无法识别 Foreach 循环 Get-ClusterResource 下的命令。但我只是想不出如何使它们从 Foreach 循环中正确传递,但仍然使用来自 $ClusterResourceInfo 的信息。
我用一百种不同的方式重写了这个,即用一个大的 Get-Cluster 变量创建一个 Invoke-command(无法让它捕获 Dependency/PossOwners,总是 $null ),将 Dependency 和 PossOwners 拆分为它们自己单独的 Invoke-Command(我能做的最好的事情是显示 System.Object[],或者当我确实显示它时,它捕获了所有的所有依赖项对象并显示在每一行上,而不是正确地拆分它)。
我已经尝试了所有我能想到或在网上找到的方法,但就是无法让它在远程正常工作。
上面的原始代码是这样输出的(这是我想要的,但我只是想修复它以便它可以远程工作):
我迫切希望得到一些智慧或指导,让我走上正轨。我尝试了很多方法,但从来没有完全得到它需要的地方,所以非常感谢和欢迎任何帮助。谢谢
我可以提出一些建议。
“Get-ClusterResource”cmdlet 失败,因为它未安装在服务器上。 您可以尝试使用 Import-Module 加载故障转移集群模块,如果失败(在非集群节点上),您可以使用以下 PowerShell 命令为 Windows PowerShell 功能添加故障转移集群模块: 添加-Windows功能 RSAT-Clustering-PowerShell
您可以尝试使用 WMI 连接到托管资源的远程集群节点吗? 您有足够的资源信息,可以编写经过筛选的 WMI 查询。
所以零碎的方法让我遇到了麻烦。在尝试将事物合并在一起时,我一直在破坏它(主要是因为我认为 %{} 加倍了)。因此,我没有合并,而是复制了已经按预期工作的部分。
最终这段代码运行良好:
$ClusterInfo = Invoke-command -computer $Computer {
Get-Cluster | Get-ClusterResource | %{
$_ | select Name,
@{ Name = "Address"; Expression = { $_ | Get-ClusterParameter -Name Address -ErrorAction SilentlyContinue | select -ExpandProperty Value } },
@{ Name = "SubnetMask"; Expression = { $_ | Get-ClusterParameter -Name SubnetMask -ErrorAction SilentlyContinue | select -ExpandProperty Value } },
@{ Name = "PossibleOwners"; Expression = { $_ | Get-ClusterOwnerNode | select OwnerNodes | select -ExpandProperty OwnerNodes } },
@{ Name = "Dependency"; Expression = { $_ | Get-ClusterResourceDependency | select -ExpandProperty "DependencyExpression" } }
}
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ClusterResourceInfo = Invoke-command -computer $Computer {
Get-ClusterResource | Select Cluster, Name, State, ResourceType, OwnerGroup, OwnerNode, IsCoreResource, IsNetworkClassResource, IsStorageClassResource | Sort-Object -Property OwnerGroup, Name
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
$ResourceInfo = @()
foreach ($rec in $ClusterResourceInfo)
{
$Owner = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).PossibleOwners
$Dependency = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).Dependency
$address = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).Address
$subnetmask = ($ClusterInfo | Where { $_.Name -eq $rec.Name }).SubnetMask
$recObj = New-Object PSObject
$recObj | Add-Member NoteProperty -Name "Cluster" -Value $rec.Cluster
$recObj | Add-Member NoteProperty -Name "Name" -Value $rec.Name
$recObj | Add-Member NoteProperty -Name "State" -Value $rec.State
$recObj | Add-Member NoteProperty -Name "Resource Type" -Value $rec.ResourceType
$recObj | Add-Member NoteProperty -Name "Owner Group" -Value $rec.OwnerGroup
$recObj | Add-Member NoteProperty -Name "Owner Node" -Value $rec.OwnerNode
$recObj | Add-Member NoteProperty -Name "Possible Owners" -Value $Owner
$recObj | Add-Member NoteProperty -Name "Dependency" -Value $Dependency
$recObj | Add-Member NoteProperty -Name "IP Address" -Value $address
$recObj | Add-Member NoteProperty -Name "Subnet Mask" -Value $subnetmask
$recObj | Add-Member NoteProperty -Name "Is Core Resource" -Value $rec.IsCoreResource
$recObj | Add-Member NoteProperty -Name "Is Network Resource" -Value $rec.IsNetworkClassResource
$recObj | Add-Member NoteProperty -Name "Is Storage Resource" -Value $rec.IsStorageClassResource
$ResourceInfo += $recObj
}
New-HTMLTable -DataTable $ResourceInfo -HideFooter -HideButtons -DisableSearch