首页 > 解决方案 > 使用 Powershell 的嵌套哈希表中的 Foreach 循环与 if/elseif

问题描述

如果组件状态不是“绿色”,我的目标是创建一个 PowerShell 脚本来监控主机硬件运行状况和警报(通过退出代码)。默认情况下,从软件 API 中提取以下信息作为哈希表。

出于可读性目的,这是 JSON 格式的信息,我使用convertto-json cmdlet 进行了转换:

"host":  {
             "serial_number":  "55555",
             "status":  "GREEN",
             "name":  "hostname",
             "raid_card":  {
                               "serial_number":  "55555",
                               "status":  "GREEN",
                               "product_name":  "PRODUCT",
                           },
             "battery":  {
                             "percent_charged":  100,
                             "health":  "HEALTHY",
                             "status":  "GREEN"
                         },
             "accelerator":  {
                                      "temperature":  36,
                                      "status":  "GREEN"
                                  },
             "logical_drives":  [
                                    "@{serial_number=55555555555; health=HEALTHY}",
                                    "@{serial_number=55555555556; health=HEALTHY}"
                                ]
         }
}

如果任何组件(电池、raid_card、加速器或逻辑驱动器)不是绿色的,则顶部的 host.status 值将变为“RED”。

我设想的逻辑是执行一个初始 if 语句,其中 if host.value 为“GREEN”,然后退出 0(表示它已启动)并输出一条消息。

否则,执行 foreach 循环以搜索并识别哪个组件不是“绿色”。这就是我坚持逻辑的地方。

我遇到的第一个问题是不知道 foreach 循环是否最适合这个问题。如果是,你怎么能构造foreach循环,因为其中一个组件,逻辑驱动器,里面有一个嵌套的哈希表。

我遇到的第二个问题是,如果状态不是“GREEN”,您如何检索组件名称?

我没有走多远,但这是我最初使用的结构:

if (host.value -eq "GREEN"){
Write-Host "Message: host hardware is healthy"
Exit 0;
}

else{
    foreach ($components in $response.host){
       if ($_.status -ne "GREEN){
       Write-Host "Message: host.??? is not healthy"
       Exit 1;
       }
}

一种替代结构是只执行 if/elseif 语句而不是 foreach 循环。这样做的问题是它不是很优雅,而且它的重复性表明有更好的方法。

if (host.value -eq "GREEN"){
Write-Host "Message: host hardware is healthy"
Exit 0;
}

else{
    if (host.raid_card.status -ne "GREEN"){
    Write-Host "Message: host.raid_card.product_name is not healthy"
    Exit 1;
    }

    elseif (host.battery.status -ne "GREEN"){
    Write-Host "Message: host battery is host.battery.status"
    Exit 1;
    }

    elseif (host.accelerator.status -ne "GREEN"{
    Write-Host "Message: accelerator temperature is host.accelerator.temperature"
    Exit 1;
    }
}

任何有关如何更好地构建它的建议将不胜感激!

标签: powershellif-statementforeachhashtablesolarwinds-orion

解决方案


I would suggest putting the components you would like to iterate one step deeper in the structure and also make sure every component has similar 'status' properties to check (which isn't the case in your json example) like so:

{
    "host": {
        "serial_number": "55555",
        "status": "GREEN",
        "name": "hostname",
        "components": {
            "raid_card": {
                "serial_number": "55555",
                "status": "GREEN",
                "product_name": "PRODUCT"
            },
            "battery": {
                "percent_charged": 100,
                "health": "HEALTHY",
                "status": "GREEN"
            },
            "accelerator": {
                "temperature": 36,
                "status": "GREEN"
            },
            "logical_drives": {
                "serial_number": "55555555555",
                "health": "HEALTHY",
                "status": "GREEN"
            }
        }
    }
}

When you have that in place, you can use code like this to check the status of each component:

# Set up an return variable (exit code)
[int]$exitCode = 0

# $machine is the variable name i used to import the json above
if ($machine.host.status -eq "GREEN") {
    Write-Host "Message: Machine $($machine.host.name) - hardware is healthy"
}
else {
    foreach ($component in $machine.host.components.PSObject.Properties) { 
        if ($component.Value.status -ne "GREEN") {
            Write-Host "Message: Machine $($machine.host.name) - $($component.Name) is not healthy"
            $exitCode = 1
        }
    }
}

Exit $exitCode

Of course you have different items in there and for now i can see the array of logical drives may be a problem. If you want to have the script tell you which logical drive is causing the status to be "not GREEN" you need to provide an if statement inside the foreach loop to iterate over every drive.


推荐阅读