Home » Как преобразовывать JSON-данные с помощью jq — CLI-гайд
Как преобразовывать JSON-данные с помощью jq — CLI-гайд

Как преобразовывать 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, вы сэкономите кучу времени на рутинных задачах и сможете создавать элегантные решения для обработки данных. Это инвестиция в себя, которая окупится уже через неделю активного использования.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked