単なるリクエスト送信で終わらせない。現場で役立つ「curl」の知られざる実践オプション
目次
開閉
Webエンジニアであれば、ほぼ毎日叩いていると言っても過言ではない curl (GitHub: curl/curl)。
APIの疎通確認をしたり、READMEに書かれたセットアップスクリプトをダウンロードしたりする際、何気なく使っている方も多いはずです。
しかし、シェルスクリプトやCI/CDパイプラインの中に組み込んだ際、「相手のサーバーが落ちていてスクリプトが無限にハングした」「HTTP 500エラーが返ってきたのにスクリプトが成功扱いで進んでしまった」といったトラブルに遭遇したことはないでしょうか。
curl は1998年の誕生から四半世紀以上にわたり現場を支え続けてきただけあり、実践的なネットワーク制御やデバッグのためのオプションが非常に充実しています。
今回は、日々のデバッグや自動化スクリプトをグッと堅牢にする「知っておくと差がつく実践オプション」をご紹介します。
シェルスクリプトで必須の「三種の神器」
まずは、自動化スクリプトやCIの中で curl を呼ぶ際に、事故を防ぐための基本セットです。
curl -fsSL https://example.com/api/data
よく目にする -fsSL という組み合わせですが、それぞれの役割を正確に把握しておくことが重要です。
-f(--fail): 最も重要です。通常、curlはサーバーから404 Not Foundや500 Internal Server Errorが返ってきても「通信自体は成功した」とみなして終了ステータス0(正常終了)を返してしまいます。-fを付けると、HTTPエラー時に終了ステータス22などの非ゼロを返してスクリプトを安全に停止させられます。-s(--silent): プログレスバーや進行状況のログ出力を非表示にします。-S(--show-error):-sと併用し、エラーが発生した時だけ標準エラー出力にエラーメッセージを表示します。-L(--location): サーバーから301や302のリダイレクトが返ってきた際、自動的にリダイレクト先のURLへ追従します。
これらを組み合わせた -fsSL は、スクリプト実行時の「安全網」として習慣にしておきたい組み合わせです。
タイムアウトと自動リトライの制御
ネットワーク越しの通信である以上、相手サーバーの一時的な過負荷やネットワーク瞬断は日常茶飯事です。無制限に待ち続けてプロセスがスタックするのを防ぐため、タイムアウトは必ず明示的に設定します。
curl -fsSL \
--connect-timeout 5 \
--max-time 15 \
--retry 3 \
--retry-delay 2 \
--retry-all-errors \
https://api.example.com/health
--connect-timeout <秒>: TCP接続が確立するまでの最大待ち時間。DNS解決やハンドシェイクが遅い場合に素早く諦めるために短め(3〜5秒)に設定します。--max-time <秒>(または-m): リクエスト開始からレスポンス完了までの全処理の最大許容時間。--retry <回数>: 通信失敗時に指定した回数だけ自動再試行します。--retry-all-errors: ネットワークエラーだけでなく、HTTP 500番台などの一時的なサーバーエラーも含めてリトライ対象にします。
レスポンス時間とHTTPステータスだけを取り出す(-w)
パフォーマンス調査やサーバーの死活監視スクリプトで非常に強力なのが、書き出し書式を指定する -w(--write-out)オプションです。
本文を破棄(-o /dev/null)し、HTTPステータスコードとレスポンスにかかった時間(秒)だけをスッキリ抽出できます。
curl -s -o /dev/null -w "HTTP: %{http_code} | Total: %{time_total}s\n" https://example.com
# 出力例:
# HTTP: 200 | Total: 0.124530s
DNS解決にかかった時間(%{time_namelookup})やSSLハンドシェイク完了時間(%{time_appconnect})も個別に取得できるため、「ページの読み込みが遅い原因がDNSなのか、サーバーの処理なのか」を手元のターミナルから一発で切り分けられます。
送受信ヘッダーと生通信の詳細ログを見る(-v と --trace-ascii)
「なぜか認証が通らない」「CORSエラーの原因が分からない」というときは、迷わず -v(--verbose)を付けます。
curl -v https://api.example.com/v1/me -H "Authorization: Bearer my-token"
>で始まる行: クライアントから送信したリクエストヘッダー<で始まる行: サーバーから返ってきたレスポンスヘッダー*で始まる行: SSL証明書の検証や接続プロセスの内部ログ
さらに、リクエストボディを含めた生のバイト列を完全にダンプしたい場合は、--trace-ascii - を指定すると通信内容の全貌が可視化されます。
まとめ
普段何気なく叩いている curl ですが、オプションの引き出しを少し増やすだけで、場当たり的な疎通確認ツールから「堅牢な自動化パイプラインの要」へと進化します。
取得したJSONレスポンスの加工やフィルタリングについては、前回の jq の記事と組み合わせることで、ターミナル完結の強力なワークフローが実現できます。あわせて参考にしてみてください。