Цикл Foreach против if/elseif во вложенной хеш-таблице с использованием Powershell
Моя цель - создать сценарий PowerShell, который отслеживает состояние оборудования хоста и выдает предупреждения (с помощью кодов выхода), если состояние компонента не "ЗЕЛЕНЫЙ". Следующая информация извлекается из программного API как хеш-таблица по умолчанию.
Для удобства чтения это информация в формате JSON, которую я преобразовал с помощью командлета convertto-json:
"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, accelerator или logic_drives) не зеленый, то значение верхнего хоста.status изменится на "КРАСНЫЙ".
Логика, которую я предполагаю, состоит в том, чтобы сделать начальный оператор if, в котором если host.value имеет значение "ЗЕЛЕНЫЙ", затем выйти из 0 (что означает, что он активен) и просто вывести сообщение.
В противном случае выполните цикл foreach, чтобы найти и определить, какой компонент не "ЗЕЛЕНЫЙ". Вот где я застрял с логикой.
Первая проблема, которую я имею, не зная, является ли цикл foreach наиболее подходящим для этой проблемы. Если это так, как вы можете структурировать цикл foreach, поскольку один из компонентов, логические диски, имеет вложенную хеш-таблицу внутри.
Вторая проблема, которая у меня есть, - как вы можете получить имя компонента, если статус не "ЗЕЛЕНЫЙ"?
Я не получил далеко, но это структура, с которой я изначально собирался:
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;
}
}
Любые рекомендации о том, как лучше структурировать это будет оценено!
1 ответ
Я бы посоветовал поместить компоненты, которые вы хотели бы сделать, на одну ступень глубже в структуре, а также убедиться, что у каждого компонента есть похожие свойства status для проверки (что не так в вашем примере с json), например так:
{
"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"
}
}
}
}
Когда у вас это есть, вы можете использовать такой код для проверки состояния каждого компонента:
# 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
Конечно, у вас есть разные предметы, и сейчас я вижу, что массив логических дисков может быть проблемой. Если вы хотите, чтобы скрипт сообщал вам, какой логический диск вызывает состояние "не ЗЕЛЕНЫЙ", вам нужно предоставить оператор if внутри цикла foreach для перебора каждого диска.