curl есть почти в любом дистрибутиве и работает одинаково на сервере, ноутбуке и в контейнере. Им проверяют API, скачивают файлы, смотрят заголовки и ищут причину, почему браузер показывает ошибку, а приложение — таймаут. Ниже — практические приёмы, а не пересказ man-страницы.
Базовый запрос и что он показывает
По умолчанию curl печатает тело ответа в stdout. Для диагностики полезнее сразу разделить заголовки и тело и подавить прогресс-бар, чтобы он не мешал в логах.
curl -sS -D headers.txt -o body.json https://api.example.com/v1/status
curl -sS -i https://example.com/ | head -n 20
curl -sS -I https://example.com/
-i включает заголовки в вывод, -I отправляет HEAD и показывает только их. -sS убирает прогресс, но оставляет сообщения об ошибках: одного -s недостаточно, иначе сбой TLS или DNS пройдёт молча.
JSON, методы и авторизация
Для JSON не нужно вручную собирать заголовки: --json ставит Content-Type: application/json и Accept: application/json. Метод задаётся -X, но для GET и POST он обычно не нужен.
curl -sS --json '{"name":"test","enabled":true}' https://api.example.com/v1/items
curl -sS -X PUT --json '{"enabled":false}' https://api.example.com/v1/items/42
curl -sS -H 'Authorization: Bearer TOKEN' https://api.example.com/v1/me
curl -sS --netrc-file ~/.netrc https://api.example.com/v1/me
Токен в командной строке попадает в историю shell и в список процессов. Для разовых проверок допустим заголовок, для регулярных задач — файл ~/.netrc с правами 600 или переменная окружения, которую подставляет обёртка. Пароль в -u user:pass тоже виден процессам, поэтому лучше curl -u user и ввод с терминала.
Коды 4xx и 5xx по умолчанию не считаются ошибкой curl: тело ответа будет выведено, а код возврата останется нулевым. Добавляйте --fail-with-body, если нужен ненулевой статус при HTTP-ошибке, но тело всё ещё важно для разбора.
Скачивание и отправка файлов
-O сохраняет файл под именем из URL, -o задаёт своё имя, -C - продолжает прерванную загрузку. Последнее работает только если сервер поддерживает Range-запросы.
curl -L -O https://example.com/releases/tool-1.2.3.tar.gz
curl -L -C - -o archive.iso https://example.com/archive.iso
curl --limit-rate 2M -o big.iso https://example.com/big.iso
curl -F 'file=@report.pdf' https://upload.example.com/files
-L обязателен для редиректов: без него вы получите страницу 301 вместо файла. Для загрузки форм используется -F, для нескольких полей — несколько -F. Если серверу нужен явный MIME-тип, помогает -F 'file=@report.pdf;type=application/pdf'.
Заголовки, cookies и кэш
Заголовки задаются флагом -H; пустое значение после двоеточия удаляет внутренний заголовок, что полезно при отладке цепочки запросов. --compressed просит сжатие и распаковывает ответ автоматически: без него при сжатом ответе вы получите бинарный поток вместо текста.
curl -sS --compressed -H 'Accept-Language: ru' https://example.com/
curl -sS -c cookies.txt -b cookies.txt https://example.com/login
curl -sS -H 'If-None-Match: "abc123"' -o /dev/null -w '%{http_code}\n' https://example.com/static/app.js
-c записывает cookies после запроса, -b читает их перед запросом; для отладки сессии удобно хранить jar в отдельном временном файле и не коммитить его. Условный запрос с If-None-Match возвращает 304, если файл не изменился: это быстрый способ проверить кэширование и сэкономить трафик.
Заголовки ответа можно сохранить через -D headers.txt или вывести в поток через -D -. Если сервер отвечает 429, сначала прочитайте Retry-After, а уже потом повторяйте запрос: добавление --retry к исчерпанной квоте только ухудшит ситуацию.
Диагностика сети
Начинайте с -v: он показывает DNS, TCP, TLS, отправленные заголовки и первый байт ответа. Для разбора инцидента полезнее трассировка в файл, чем экран с быстрым выводом.
curl -v --connect-timeout 5 --max-time 30 https://example.com/
curl --trace-time --trace-ascii trace.txt https://example.com/
curl -4 -sS -o /dev/null -w '%{http_code} %{time_namelookup} %{time_connect} %{time_total}\n' https://example.com/
curl --resolve example.com:443:192.0.2.10 https://example.com/
Формат -w — самый быстрый способ отделить медленный DNS от медленного TLS и медленного приложения. Если time_namelookup близок к time_total, проблема в резолвере; если растёт time_connect — до сервера не доходит TCP; если основной вклад даёт time_appconnect — виноват TLS или промежуточный узел.
--resolve подставляет нужный IP для конкретного имени, не меняя /etc/hosts: удобно проверить новый балансировщик до переключения DNS. Флаги -4 и -6 помогают, когда IPv6 настроен, но не работает. Ошибка сертификата обычно означает неверные часы, отсутствующий корневой сертификат или цепочку; -k допустим только как временный диагностический инструмент, а не как настройка.
В -w полезны не только time_total, но и time_starttransfer, size_download и speed_download. Первый показывает, когда сервер отдал первый байт, второй — реальный объём, третий — среднюю скорость. Если соединение установлено быстро, а первый байт идёт долго, ищите проблему в приложении или базе, а не в сети.
Надёжные скрипты и чек-лист
В автоматизации важны таймауты, повторы и проверка кода. Без --max-time скрипт может ждать вечно, а без проверки статуса — считать успехом страницу ошибки. Тело неуспешного ответа сохраняйте рядом с логом: по нему видно, дело в запросе или в сервере.
code=$(curl -sS --max-time 20 -o /tmp/health.body -w '%{http_code}' https://example.com/health)
[ "$code" = "200" ] || { echo "HTTP $code"; exit 1; }
curl -sS --retry 3 --retry-delay 2 --retry-connrefused --fail-with-body https://api.example.com/v1/items
- Проверьте
curl --version: поддержка HTTP/2, zstd и TLS зависит от сборки. - Для cookies используйте
-c cookies.txtи-b cookies.txt, а не ручной заголовок. - Не выводите токены в лог; маскируйте их при отладке.
- Ограничивайте скорость и размер на тестовых стендах, чтобы не устроить нагрузку чужому API.
- Проверяйте API только с разрешения владельца и соблюдайте лимиты запросов.
Итог
curl закрывает три задачи: забрать данные, отправить данные и объяснить, где именно ломается соединение. Запомните минимум: -sS для тишины без потери ошибок, --json для API, -L -C - для файлов, -w и --trace-ascii для диагностики, --max-time и проверка кода для скриптов. Этих приёмов хватает в большинстве повседневных ситуаций.