- Home »

Как преобразовывать JSON-данные с помощью jq — CLI-гайд
Если вы когда-нибудь сталкивались с обработкой JSON на сервере, то наверняка помните эти болезненные моменты с парсингом через grep, sed или awk. Это как пытаться есть суп вилкой — технически возможно, но зачем мучиться? Вот тут на сцену выходит jq — легендарная CLI-утилита, которая превращает работу с JSON из кошмара в удовольствие.
Эта статья поможет вам освоить jq от азов до продвинутых техник. Мы разберём, как правильно фильтровать, трансформировать и обрабатывать JSON-данные в скриптах автоматизации, мониторинга и деплоя. Без воды — только практические примеры и реальные кейсы из жизни сисадмина.
Что такое jq и зачем он нужен
jq — это как sed для JSON. Легковесная командная утилита, которая позволяет извлекать, фильтровать и трансформировать JSON-данные одной строкой. Написана на C, поэтому работает быстро даже с большими файлами.
Основные возможности:
- Извлечение конкретных полей из JSON
- Фильтрация массивов по условиям
- Трансформация структуры данных
- Математические операции над числовыми значениями
- Объединение и разделение JSON-объектов
- Работа с вложенными структурами любой глубины
Установка и первый запуск
Установка максимально простая. На большинстве дистрибутивов jq есть в стандартных репозиториях:
# Ubuntu/Debian
sudo apt install jq
# CentOS/RHEL
sudo yum install jq
# или для новых версий
sudo dnf install jq
# Arch Linux
sudo pacman -S jq
# macOS
brew install jq
Проверяем установку:
jq --version
# jq-1.6
Если вы работаете на VPS или выделенном сервере, jq должен быть в вашем обязательном наборе утилит.
Основы работы с jq
Базовый синтаксис:
jq 'filter' file.json
# или через pipe
echo '{"name": "John", "age": 30}' | jq '.name'
Давайте разберём основные операторы на примерах:
Извлечение полей
# Исходный JSON
echo '{"server": {"hostname": "web01", "ip": "192.168.1.10", "status": "active"}}' | jq '.server.hostname'
# "web01"
# Множественное извлечение
echo '{"cpu": 85, "memory": 76, "disk": 45}' | jq '.cpu, .memory'
# 85
# 76
Работа с массивами
# Массив серверов
echo '[{"name": "web01", "cpu": 85}, {"name": "web02", "cpu": 45}]' | jq '.[0].name'
# "web01"
# Все элементы массива
echo '[{"name": "web01"}, {"name": "web02"}]' | jq '.[] | .name'
# "web01"
# "web02"
# Длина массива
echo '[1,2,3,4,5]' | jq 'length'
# 5
Практические примеры для сисадминов
Мониторинг системы
Допустим, у вас есть JSON с метриками сервера:
cat > metrics.json << 'EOF'
{
"timestamp": "2024-01-15T10:30:00Z",
"servers": [
{"hostname": "web01", "cpu": 85, "memory": 76, "disk": 45, "status": "warning"},
{"hostname": "web02", "cpu": 45, "memory": 60, "disk": 30, "status": "ok"},
{"hostname": "db01", "cpu": 90, "memory": 85, "disk": 70, "status": "critical"}
]
}
EOF
Найдём серверы с высокой нагрузкой CPU:
# Серверы с CPU > 80%
cat metrics.json | jq '.servers[] | select(.cpu > 80) | .hostname'
# "web01"
# "db01"
# Полная информация о критичных серверах
cat metrics.json | jq '.servers[] | select(.status == "critical")'
# {
# "hostname": "db01",
# "cpu": 90,
# "memory": 85,
# "disk": 70,
# "status": "critical"
# }
Обработка логов
Парсинг JSON-логов nginx или приложений:
# Лог-файл в формате JSON
cat > app.log << 'EOF'
{"timestamp": "2024-01-15T10:30:01Z", "level": "ERROR", "message": "Database connection failed", "user_id": 12345}
{"timestamp": "2024-01-15T10:30:02Z", "level": "INFO", "message": "User logged in", "user_id": 67890}
{"timestamp": "2024-01-15T10:30:03Z", "level": "ERROR", "message": "Payment processing failed", "user_id": 12345}
EOF
# Только ошибки
cat app.log | jq 'select(.level == "ERROR") | .message'
# "Database connection failed"
# "Payment processing failed"
# Группировка по пользователям
cat app.log | jq 'group_by(.user_id) | .[] | {user_id: .[0].user_id, count: length}'
Работа с API
Получение данных через API и их обработка:
# Получаем информацию о репозитории GitHub
curl -s "https://api.github.com/repos/stedolan/jq" | jq '{
name: .name,
stars: .stargazers_count,
forks: .forks_count,
language: .language,
updated: .updated_at
}'
# Список всех веток
curl -s "https://api.github.com/repos/stedolan/jq/branches" | jq '.[].name'
Продвинутые техники
Трансформация данных
Часто нужно изменить структуру JSON для интеграции с другими системами:
# Исходные данные
echo '{
"users": [
{"id": 1, "name": "John", "email": "john@example.com", "active": true},
{"id": 2, "name": "Jane", "email": "jane@example.com", "active": false}
]
}' | jq '
.users
| map(select(.active))
| map({user_id: .id, full_name: .name, contact: .email})
'
Математические операции
# Подсчёт средней нагрузки
echo '{
"servers": [
{"name": "web01", "cpu": 85, "memory": 76},
{"name": "web02", "cpu": 45, "memory": 60},
{"name": "db01", "cpu": 90, "memory": 85}
]
}' | jq '
.servers
| map(.cpu)
| add / length
'
# 73.33333333333333
# Суммарное потребление памяти
echo '[{"memory": 1024}, {"memory": 2048}, {"memory": 512}]' | jq 'map(.memory) | add'
# 3584
Условная логика
# Классификация серверов по нагрузке
echo '[{"name": "web01", "cpu": 85}, {"name": "web02", "cpu": 45}]' | jq '
.[] | {
name: .name,
cpu: .cpu,
status: (if .cpu > 80 then "high" elif .cpu > 60 then "medium" else "low" end)
}
'
Полезные флаги и опции
Флаг | Описание | Пример |
---|---|---|
-r | Вывод без кавычек (raw output) | jq -r '.name' |
-c | Компактный вывод | jq -c '.' |
-s | Читать весь ввод как массив | jq -s '.' |
-e | Установить код возврата на основе вывода | jq -e '.error' |
-n | Не читать ввод | jq -n '{now: now}' |
-S | Сортировать ключи | jq -S '.' |
Интеграция с другими утилитами
Связка с curl
# Скрипт для мониторинга API
#!/bin/bash
API_URL="https://api.service.com/health"
response=$(curl -s "$API_URL")
status=$(echo "$response" | jq -r '.status')
uptime=$(echo "$response" | jq -r '.uptime')
if [ "$status" != "ok" ]; then
echo "ALERT: Service is down!" | mail -s "Service Alert" admin@company.com
fi
echo "Service status: $status, uptime: $uptime"
Парсинг конфигурационных файлов
# Извлечение настроек из JSON-конфига
cat config.json | jq -r '.database.host'
cat config.json | jq -r '.database.port'
# Или одной командой
cat config.json | jq -r '.database | "\(.host):\(.port)"'
Генерация конфигов
# Создание nginx-конфига из JSON
echo '{
"servers": [
{"name": "web01", "ip": "192.168.1.10"},
{"name": "web02", "ip": "192.168.1.11"}
]
}' | jq -r '
.servers[] |
"upstream backend {\n server \(.ip):80;\n}"
'
Сравнение с альтернативами
Утилита | Плюсы | Минусы | Когда использовать |
---|---|---|---|
jq | Быстрый, мощный, стандарт де-факто | Специфичный синтаксис | Основной инструмент для JSON |
jshon | Простой синтаксис | Менее функциональный | Простые операции |
json_pp | Идёт с Perl | Только форматирование | Только для prettify |
python -m json.tool | Везде есть Python | Только форматирование | Быстрое форматирование |
Автоматизация и скрипты
Скрипт для деплоя
#!/bin/bash
# deploy.sh - простой скрипт деплоя с использованием jq
CONFIG_FILE="deploy.json"
# Читаем конфигурацию
SERVERS=$(jq -r '.servers[].hostname' "$CONFIG_FILE")
APP_PATH=$(jq -r '.app_path' "$CONFIG_FILE")
GIT_REPO=$(jq -r '.git_repo' "$CONFIG_FILE")
echo "Deploying to servers: $SERVERS"
for server in $SERVERS; do
echo "Deploying to $server..."
ssh "$server" "cd $APP_PATH && git pull $GIT_REPO && sudo systemctl restart app"
done
Мониторинг дискового пространства
#!/bin/bash
# disk_monitor.sh
df -h | tail -n +2 | while read line; do
usage=$(echo "$line" | awk '{print $5}' | sed 's/%//')
filesystem=$(echo "$line" | awk '{print $1}')
if [ "$usage" -gt 80 ]; then
alert=$(jq -n \
--arg fs "$filesystem" \
--arg usage "$usage" \
'{
"timestamp": now,
"alert": "disk_space",
"filesystem": $fs,
"usage_percent": ($usage | tonumber),
"severity": "warning"
}')
echo "$alert" >> /var/log/disk_alerts.json
fi
done
Обработка больших файлов
При работе с большими JSON-файлами важно учитывать производительность:
# Для больших файлов используйте streaming
jq -c '.[]' large_file.json | while read line; do
echo "$line" | jq '.field'
done
# Или используйте --stream для очень больших файлов
jq --stream 'select(.[0][0] == "field") | .[1]' huge_file.json
Отладка и тестирование jq-выражений
Для отладки сложных выражений используйте:
# Пошаговая отладка
echo '{"a": {"b": [1,2,3]}}' | jq '.a | debug | .b | debug | .[]'
# Проверка типов
echo '{"num": 42, "str": "hello"}' | jq '.num | type'
# "number"
Интересные факты и нестандартные применения
jq можно использовать не только для JSON:
- Генерация данных: jq умеет создавать JSON из ничего с помощью флага -n
- Математический калькулятор: jq -n '(1 + 2) * 3'
- Работа с датами: jq -n 'now | strftime("%Y-%m-%d")'
- Генерация UUID: можно интегрировать с uuidgen
# Создание тестовых данных
jq -n '
[range(10) | {
id: .,
name: "user\(.)",
email: "user\(.)@example.com",
created_at: (now - (. * 86400))
}]
'
Заключение и рекомендации
jq — это must-have инструмент для любого сисадмина, который работает с современными сервисами. API везде возвращают JSON, логи всё чаще пишутся в JSON, конфигурационные файлы тоже переходят на JSON.
Где обязательно использовать jq:
- Обработка ответов от REST API
- Парсинг структурированных логов
- Автоматизация деплоя и мониторинга
- Трансформация данных между системами
- Создание отчётов из JSON-данных
Практические советы:
- Начинайте с простых выражений, постепенно усложняя
- Используйте jq -r для вывода без кавычек в скриптах
- Комбинируйте с другими утилитами через pipe
- Не забывайте про обработку ошибок в production-скриптах
- Изучите встроенные функции — их очень много
Официальная документация доступна на https://stedolan.github.io/jq/, а интерактивная песочница для экспериментов — https://jqplay.org/.
Освоив jq, вы сэкономите кучу времени на рутинных задачах и сможете создавать элегантные решения для обработки данных. Это инвестиция в себя, которая окупится уже через неделю активного использования.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.