{ “system_role”: “SRE / DevOps Engineer”, “technical_stack”: [“curl”, “jq”, “Bash”, “systemd”], “objective”: “Design a robust API validation workflow with error handling.”, “style”: “Professional, Tactical, Practical” }
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
curlとjqを用いたREST API自動検証の堅牢化:エラーハンドリングと再試行戦略
【導入と前提】
curlで取得したJSONをjqでパースし、再試行と異常検知を組み込んだ堅牢なAPI自動検証の仕組みを構築します。
OS: GNU/Linux (Ubuntu 22.04 LTS / RHEL 9 等)
ツール: curl (7.64+), jq (1.6+), bash (4.0+)
【処理フローと設計】
graph TD
A["開始"] --> B{"curl実行"}
B -->|失敗/タイムアウト| C["再試行ロジック"]
C -->|上限到達| D["エラー終了/通知"]
B -->|成功| E["HTTPステータス確認"]
E -->|200以外| D
E -->|200 OK| F["jqによるスキーマ/値検証"]
F -->|不正データ| D
F -->|正常データ| G["成功処理/クリーンアップ"]
G --> H["終了"]
取得フェーズ:
curlの組み込みリトライ機能とタイムアウト設定を活用し、一時的なネットワーク断に対応。検証フェーズ:
jqの終了コード (-e) を利用し、特定のフィールドの存在や期待される値を厳密にチェック。終了フェーズ: 一時ファイルの確実な削除と、標準エラー出力へのログ集約。
【実装:堅牢な自動化スクリプト】
#!/usr/bin/env bash
# set -e: エラー発生時に即座に終了
# set -u: 未定義変数の参照時にエラー
# set -o pipefail: パイプライン途中のエラーも検知
set -euo pipefail
# ---------------------------------------------------------
# 設定・変数定義
# ---------------------------------------------------------
readonly API_URL="https://api.example.com/v1/health"
readonly EXPECTED_VERSION="1.2.0"
readonly TEMP_FILE=$(mktemp /tmp/api_res.XXXXXX.json)
# 終了時に必ず一時ファイルを削除
trap 'rm -f "${TEMP_FILE}"' EXIT
echo "[INFO] API検証開始: ${API_URL}"
# ---------------------------------------------------------
# 1. APIリクエスト実行 (curl)
# ---------------------------------------------------------
# -s: 進捗表示非表示
# -S: エラー時はメッセージ出力
# -L: リダイレクト追従
# --retry: 通信失敗時の再試行回数
# --retry-delay: 再試行の間隔(秒)
# --max-time: 全体のタイムアウト(秒)
# -w: レスポンスコードのみを変数に格納
HTTP_STATUS=$(curl -sSL \
--retry 3 \
--retry-delay 2 \
--max-time 10 \
-o "${TEMP_FILE}" \
-w "%{http_code}" \
"${API_URL}")
# ステータスコードが200かチェック
if [ "$HTTP_STATUS" -ne 200 ]; then
echo "[ERROR] APIリクエスト失敗 ステータスコード: ${HTTP_STATUS}" >&2
exit 1
fi
# ---------------------------------------------------------
# 2. JSON構造・値の検証 (jq)
# ---------------------------------------------------------
# -e: 抽出結果が null または false の場合に終了コード 1 を返す
# .status == "ok" かつ .version が期待値か確認
if ! jq -e ".status == \"ok\" and .version == \"${EXPECTED_VERSION}\"" "${TEMP_FILE}" > /dev/null; then
echo "[ERROR] レスポンス内容が不正です" >&2
echo "内容: $(cat "${TEMP_FILE}")" >&2
exit 1
fi
echo "[SUCCESS] API検証正常終了 (Version: ${EXPECTED_VERSION})"
補足:systemdによる定期実行の構成例
API監視をデーモン化または定期実行する場合、以下のユニットファイルを /etc/systemd/system/api-check.service として配置します。
[Unit] Description=API Health Checker After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/api-check.sh User=monitoring-user # 環境変数の漏洩を防ぐため、認証情報はファイルから読み込む EnvironmentFile=-/etc/default/api-check [Install] WantedBy=multi-user.target
【検証と運用】
正常系の確認
スクリプトを実行し、終了コードを確認します。
bash api-check.sh echo $? # 0 であれば成功
エラー時の確認
systemd 経由で実行している場合、journalctl を使用して原因を特定します。
# 失敗した直近のログを確認 journalctl -u api-check.service -n 50 --no-pager
【トラブルシューティングと落とし穴】
権限問題:
mktempで作成するディレクトリに実行ユーザーの書込権限があるか確認してください。sudoで実行する場合はtrapによる削除が適切に行われるよう注意が必要です。環境変数の漏洩: APIキーなどの機密情報はスクリプト内にハードコードせず、
EnvironmentFileやexport済みの変数から読み込み、set -x(デバッグ実行)を使用する際は機密情報が出力されないよう保護してください。jqの互換性: 古いディストリビューション(CentOS 7等)では
jq 1.5が使われている場合があり、一部の関数(any,all等)の挙動が異なる可能性があります。
【まとめ】
運用の冪等性と堅牢性を維持するためのポイント:
異常終了の早期化:
set -euo pipefailにより、予期せぬ挙動を未然に防ぐ。再試行の標準化:
curl自体のリトライ機能を使い、シェル側で複雑なループを書かない。状態の局所化:
trapとmktempを活用し、実行環境にゴミ(一時ファイル)を残さない。

