Вопрос или проблема
У меня есть JSON, который выглядит следующим образом:
{
"type": "server-firmwareinventory-list-1",
"members": [
{
"type": "sever-hardware-firmware-1",
"category": "sever-hardware",
"serverName": "my-host",
"components": [
{
"componentName": "firmware-hdd-8051bb7e9c",
"componentDescription": "Прошивка дисков VS000480KXALB, VS003840KWXFQ, VS001920KWXFP и VS000960KWXFN",
"componentVersion": "85032G00-4.1"
},
{
"componentName": "Системный ROM",
"componentDescription": "SystemRomActive",
"componentVersion": "A46 v2.80 (07/31/2023)"
},
{
"componentName": "Резервный системный ROM",
"componentDescription": "SystemRomBackup",
"componentVersion": "A46 v2.60 (08/11/20223)"
}
],
"serverFirmwareSettings": null
}
]
}
Я могу успешно получить активный системный ROM для каждого сервера с помощью (${FIRMW} указывает на файл, содержащий JSON).
jq -r '.members[] | {"serverName": .serverName, "system-firmware": .components[] | select(.componentName=="System ROM") | .componentVersion }' ${FIRMW}
Я хотел добавить резервный системный ROM, поэтому я попробовал:
jq -r '.members[] | {"serverName": .serverName, "system-firmware": .components[] | select(.componentName=="System ROM") | .componentVersion, "system-firmware-backup": | select(.componentName=="Redundant System ROM") | .componentVersion }' ${FIRMW}
но это выдает мне ошибку синтаксиса, неожиданное ‘|’ на первой строке. Есть идеи, как это исправить?
Вы забыли отфильтровать массив compontents
при выборе Redundant System ROM
.
Исправленный вариант вашего кода с добавлением некоторых сокращений (обратите внимание, что -r
не нужен, так как вы выводите JSON, а не сырые строки):
jq '.members[] |
{
serverName,
"system-firmware":
.components[] | select(.componentName == "System ROM").componentVersion,
"system-firmware-backup":
.components[] | select(.componentName == "Redundant System ROM").componentVersion
}' file
С учетом данных в вопросе, это даст вам следующий JSON-документ:
{
"serverName": "my-host",
"system-firmware": "A46 v2.80 (07/31/2023)",
"system-firmware-backup": "A46 v2.60 (08/11/20223)"
}
Ответ или решение
Как выбрать несколько элементов из массива с помощью jq
В современных системах управления конфигурациями и мониторинга оборудования часто возникает необходимость извлекать информация из JSON-структур. В рамках этой статьи мы рассмотрим, как использовать утилиту jq
для извлечения нескольких элементов из массива JSON, основываясь на предоставленном примере.
Пример структуры JSON
Для начала, рассмотрим данную JSON-структуру, содержащую информацию о сервере и его компонентах:
{
"type": "server-firmwareinventory-list-1",
"members": [
{
"type": "sever-hardware-firmware-1",
"category": "sever-hardware",
"serverName": "my-host",
"components": [
{
"componentName": "firmware-hdd-8051bb7e9c",
"componentDescription": "VS000480KXALB, VS003840KWXFQ, VS001920KWXFP, and VS000960KWXFN Drives firmware",
"componentVersion": "85032G00-4.1"
},
{
"componentName": "System ROM",
"componentDescription": "SystemRomActive",
"componentVersion": "A46 v2.80 (07/31/2023)"
},
{
"componentName": "Redundant System ROM",
"componentDescription": "SystemRomBackup",
"componentVersion": "A46 v2.60 (08/11/20223)"
}
],
"serverFirmwareSettings": null
}
]
}
Цель
Наша задача заключается в извлечении двух параметров версий прошивки: активной прошивки (System ROM) и резервной прошивки (Redundant System ROM) для каждого сервера.
Изначальная попытка
Вы уже успешно извлекали активную прошивку с помощью следующей команды:
jq -r '.members[] | {"serverName": .serverName, "system-firmware": .components[] | select(.componentName == "System ROM") | .componentVersion }' ${FIRMW}
Однако вы столкнулись с синтаксической ошибкой при попытке дополнить команду для извлечения резервной прошивки:
jq -r '.members[] | {"serverName": .serverName, "system-firmware": .components[] | select(.componentName == "System ROM") | .componentVersion, "system-firmware-backup": | select(.componentName == "Redundant System ROM") | .componentVersion }' ${FIRMW}
Поправленный вариант команды
Ошибки связаны с тем, что в последнем выражении вы забыли отфильтровать массив components
для резервной прошивки. Кроме того, использование флага -r
излишне, так как мы выводим JSON, а не сырой текст. Вот исправленный вариант команды:
jq '.members[] | {
serverName,
"system-firmware": .components[] | select(.componentName == "System ROM").componentVersion,
"system-firmware-backup": .components[] | select(.componentName == "Redundant System ROM").componentVersion
}' ${FIRMW}
Ожидаемый результат
В результате выполнения исправленной команды, вы получите следующий JSON-объект:
{
"serverName": "my-host",
"system-firmware": "A46 v2.80 (07/31/2023)",
"system-firmware-backup": "A46 v2.60 (08/11/20223)"
}
Заключение
Использование утилиты jq
для работы с JSON данными позволяет гибко и эффективно извлекать нужную информацию. В данном примере мы рассмотрели, как выбрать несколько компонентов из массива и избежать синтаксических ошибок при работе с фильтрами. Эти навыки помогут вам в управлении конфигурациями и мониторинге аппаратуры с использованием стандартных инструментов командной строки.
Теперь вы обладаете необходимыми знаниями для эффективного извлечения данных из JSON, что улучшает работу с системами управления и поддержкой серверов.