Modern QA2026grep, curl и jq
Join

Course19 Linux & Command Line

Foundations · Chapter 19

grep, curl и jq

Updated Jul 2026

Большая тройка для QA-инженеров

Три команды справляются с подавляющим большинством задач QA-расследований в командной строке: grep для поиска по логам и файлам, curl для выполнения HTTP-запросов и jq для парсинга JSON-ответов. Освойте эти три инструмента, и вы сможете диагностировать большинство проблем из терминала.

grep -- Поиск по логам и файлам

grep ищет шаблоны в файлах и выводит совпавшие строки. Это ваш первый инструмент при расследовании сбоев в лог-файлах.

Базовое использование

# Найти строки с ERROR в лог-файле
grep "ERROR" /var/log/app/application.log

# Поиск без учёта регистра
grep -i "null pointer" /var/log/app/application.log

# Показать 3 строки контекста вокруг каждого совпадения (до и после)
grep -C 3 "ERROR" /var/log/app/application.log

# Показать только 3 строки перед совпадением
grep -B 3 "ERROR" /var/log/app/application.log

# Показать только 3 строки после совпадения
grep -A 3 "ERROR" /var/log/app/application.log

Поиск по нескольким файлам

# Рекурсивный поиск во всех тестовых файлах
grep -r "data-testid=\"checkout" tests/

# Рекурсивный поиск с отображением имени файла
grep -rn "data-testid=\"checkout" tests/
# tests/checkout.spec.ts:15:  await page.locator('[data-testid="checkout"]').click()

# Поиск только по определённым типам файлов
grep -r --include="*.ts" "waitForTimeout" tests/

# Исключить каталоги из поиска
grep -r --exclude-dir=node_modules "TODO" .

Подсчёт и фильтрация

# Подсчёт совпавших строк
grep -c "ERROR" /var/log/app/application.log
# Вывод: 47

# Подсчёт ошибок 500 в логах nginx
grep "HTTP 500" /var/log/nginx/access.log | wc -l

# Показать только совпавшую часть строки (не всю строку)
grep -o "HTTP [0-9]\{3\}" /var/log/nginx/access.log | sort | uniq -c | sort -rn
# Вывод:
#   12847 HTTP 200
#     234 HTTP 404
#      47 HTTP 500
#      12 HTTP 503

# Инвертировать совпадение: показать строки, которые НЕ совпадают
grep -v "healthcheck" /var/log/app/application.log
# Исключить шумные строки проверок здоровья из анализа логов

# Несколько шаблонов (логика ИЛИ)
grep -E "ERROR|FATAL|CRITICAL" /var/log/app/application.log

Регулярные выражения с grep

# Найти строки с временными метками в определённом диапазоне
grep -E "2024-01-15 14:3[0-9]:" /var/log/app/application.log

# Найти email-адреса
grep -oE "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" users.txt

# Найти IP-адреса
grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log

curl -- Выполнение HTTP-запросов

curl отправляет HTTP-запросы из командной строки. Незаменимый инструмент для быстрого тестирования API, проверок здоровья и отладки сетевых проблем.

Базовые запросы

# GET-запрос
curl https://api.example.com/users

# Форматированный вывод JSON-ответа (через jq)
curl -s https://api.example.com/users | jq .

# POST с JSON-телом
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name": "Test User", "email": "test@example.com"}'

# PUT-запрос
curl -X PUT https://api.example.com/users/123 \
  -H "Content-Type: application/json" \
  -d '{"name": "Updated User"}'

# DELETE-запрос
curl -X DELETE https://api.example.com/users/123 \
  -H "Authorization: Bearer $TOKEN"

Исследование ответов

# Только заголовки ответа (HEAD-запрос)
curl -I https://api.example.com/users
# HTTP/2 200
# content-type: application/json
# cache-control: no-cache

# Подробный вывод (отладка проблем соединения)
curl -v https://api.example.com/users
# Показывает: DNS-разрешение, TCP-соединение, TLS-рукопожатие, заголовки запроса, заголовки ответа

# Показать заголовки ответа вместе с телом
curl -i https://api.example.com/users

# Показать только HTTP-код статуса
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/users
# Вывод: 200

Измерение времени запросов

# Замер времени запроса (полезно для тестирования производительности)
curl -w "\nTime: %{time_total}s\nHTTP Code: %{http_code}\n" \
  -o /dev/null -s https://api.example.com/users
# Вывод:
# Time: 0.245s
# HTTP Code: 200

# Подробная разбивка по фазам
curl -w "\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nFirst byte: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  -o /dev/null -s https://api.example.com/users

Практические сценарии curl

# Загрузка файла
curl -X POST https://api.example.com/upload \
  -F "file=@screenshot.png" \
  -H "Authorization: Bearer $TOKEN"

# Следовать перенаправлениям
curl -L https://example.com/old-url

# Сохранить ответ в файл
curl -o response.json https://api.example.com/users

# Отправить запрос с куками
curl -b "session=abc123" https://api.example.com/profile

# Установить таймаут (предотвратить зависание)
curl --max-time 30 https://slow-api.example.com/endpoint

# Повторить при сбое
curl --retry 3 --retry-delay 5 https://flaky-api.example.com/endpoint

jq -- Парсинг JSON

jq -- это консольный процессор JSON. Большинство API возвращают JSON, и jq позволяет извлекать, фильтровать и трансформировать эти данные.

Базовое использование

# Форматированный вывод JSON
curl -s https://api.example.com/users | jq .

# Извлечь конкретное поле
curl -s https://api.example.com/users/1 | jq '.name'
# Вывод: "John Doe"

# Извлечь вложенное поле
curl -s https://api.example.com/users/1 | jq '.address.city'
# Вывод: "New York"

# Извлечь из массива
curl -s https://api.example.com/users | jq '.[0].name'
# Вывод: "John Doe" (имя первого пользователя)

# Получить все имена из массива
curl -s https://api.example.com/users | jq '.[].name'
# Вывод:
# "John Doe"
# "Jane Smith"
# "Bob Wilson"

Фильтрация и выборка

# Фильтрация элементов массива
curl -s https://api.example.com/users | jq '.[] | select(.role == "admin")'

# Фильтрация по числовому сравнению
curl -s https://api.example.com/orders | jq '.[] | select(.total > 100)'

# Фильтрация по содержимому строки
curl -s https://api.example.com/users | jq '.[] | select(.email | contains("@example.com"))'

# Несколько условий
curl -s https://api.example.com/users | jq '.[] | select(.role == "admin" and .active == true)'

Трансформация данных

# Подсчёт элементов в массиве
curl -s https://api.example.com/users | jq length
# Вывод: 42

# Создать объект новой формы
curl -s https://api.example.com/users | jq '.[] | {name: .name, email: .email}'

# Извлечь конкретные поля в CSV-подобный формат
curl -s https://api.example.com/users | jq -r '.[] | [.id, .name, .email] | @csv'
# Вывод:
# 1,"John Doe","john@example.com"
# 2,"Jane Smith","jane@example.com"

# Сортировка по полю
curl -s https://api.example.com/users | jq 'sort_by(.created_at) | reverse'

# Группировка по полю
curl -s https://api.example.com/users | jq 'group_by(.role) | .[] | {role: .[0].role, count: length}'

Работа с локальными файлами

# Парсинг локального JSON-файла
jq '.dependencies' package.json

# Извлечение тестовой конфигурации
jq '.scripts | to_entries | .[] | select(.key | startswith("test"))' package.json

# Модификация JSON (полезно для тестовых данных)
jq '.baseURL = "https://staging.example.com"' config.json > config-staging.json

Комбинирование grep, curl и jq

Настоящая мощь проявляется при комбинировании этих инструментов:

# Проверить здоровье API и уведомить при ненулевом коде
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
[ "$STATUS" -ne 200 ] && echo "API is down! Status: $STATUS"

# Найти всех админов и посчитать их
curl -s https://api.example.com/users | jq '[.[] | select(.role == "admin")] | length'

# Искать конкретные данные в ответе API
curl -s https://api.example.com/products | jq '.[] | select(.name | test(".*phone.*"; "i"))'

# Мониторинг времени отклика эндпоинта в цикле
while true; do
  TIME=$(curl -s -o /dev/null -w "%{time_total}" https://api.example.com/health)
  echo "$(date): ${TIME}s"
  sleep 10
done

awk и sed (краткий справочник)

Два дополнительных инструмента обработки текста, дополняющие grep:

# awk: Вычислить среднее время отклика из лога
awk '{sum += $4; count++} END {print sum/count "ms"}' response-times.log

# awk: Вывести конкретные столбцы
awk '{print $1, $4, $7}' /var/log/nginx/access.log

# sed: Заменить staging URL на production URL
sed 's/staging.example.com/prod.example.com/g' test-config.json

# sed: Удалить строки, соответствующие шаблону
sed '/healthcheck/d' application.log

# sed: Вставить текст в начало файла
sed -i '1i # This is a test configuration file' config.json

ssh и scp

Доступ к удалённым серверам необходим для QA-работы в нелокальных окружениях:

# Подключиться к удалённому серверу
ssh qa@staging-server.example.com

# Выполнить команду на удалённом сервере без интерактивной сессии
ssh qa@staging-server.example.com "ps aux | grep node"

# Скопировать результаты тестов с удалённого на локальный
scp qa@staging-server.example.com:/var/log/test-results.xml ./

# Скопировать файл с локального на удалённый
scp test-data.json qa@staging-server.example.com:/tmp/

# SSH-туннель: доступ к удалённой базе данных локально
ssh -L 5432:localhost:5432 qa@staging-server.example.com
# Теперь подключайтесь к localhost:5432 для доступа к удалённому Postgres

Практическое упражнение

  1. Используйте grep для поиска всех строк ERROR в лог-файле, затем подсчитайте количество уникальных сообщений об ошибках
  2. Используйте curl для выполнения GET- и POST-запросов к публичному API (например, https://jsonplaceholder.typicode.com)
  3. Используйте jq для извлечения и фильтрации данных из ответа API
  4. Объедините все три: получите список пользователей через curl, разберите через jq для поиска администраторов и пропустите через grep для поиска определённого email-домена
  5. Замерьте время API-запроса с помощью curl -w и определите, какая фаза (DNS, connect, TLS, first byte) самая медленная
  6. Напишите однострочник, который мониторит эндпоинт каждые 10 секунд и логирует код статуса и время отклика