{
"style": "SRE/DevOps professional",
"tools": ["curl", "jq", "systemd", "bash"],
"reliability_level": "Production-ready (Draft)",
"security_focus": ["Environment variables", "Error handling", "Least privilege"]
}
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
REST API連携の堅牢化:curlとjqによる自動バリデーション実装
【導入と前提】
APIレスポンスの構造検証とエッジケース対応をシェルスクリプトで自動化し、監視の信頼性と運用継続性を向上させます。
OS: GNU/Linux (Ubuntu 22.04+, RHEL 8+ 推奨)
必須ツール:
curl(7.68.0+),jq(1.6+)前提: RESTful APIへの疎通権限および環境変数の設定権限
【処理フローと設計】
graph TD
A["Start: Script Execution"] --> B["Environment Check"]
B --> C["Execute curl with Retries"]
C --> D{"HTTP Status 200?"}
D -- No --> E["Logging & Alerting"]
D -- Yes --> F["jq Schema Validation"]
F -- Fail --> E
F -- Success --> G["Post-Processing / Success"]
G --> H["End: Cleanup"]
E --> H
本フローでは、まず通信レイヤーの正常性(HTTP Status)を確認し、次にデータレイヤーの整合性(JSON Schema相当のチェック)を jq で検証します。これにより、APIのサイレントフェイル(200 OKだがデータが空など)を確実に検知します。
【実装:堅牢な自動化スクリプト】
#!/usr/bin/env bash
# ==============================================================================
# API Validation Script
# Description: curlでAPIを叩き、jqでレスポンスの整合性を検証する
# ==============================================================================
set -euo pipefail # エラー時に停止、未定義変数参照禁止、パイプ途中エラーの捕捉
IFS=$'\n\t'
# 設定項目(環境変数からの読み込みを推奨)
API_URL="${API_URL:-https://api.example.com/v1/health}"
API_TOKEN="${API_TOKEN:-}"
TIMEOUT_SEC=10
RETRY_COUNT=3
# 一時ファイルの管理
TMP_RES=$(mktemp)
trap 'rm -f "$TMP_RES"' EXIT # 終了時に必ず一時ファイルを削除
echo "[INFO] Starting API validation for: ${API_URL}"
# 1. APIリクエスト実行
# -s: プログレス表示抑制 / -S: エラー表示 / -f: HTTPエラー時に失敗させる
# -L: リダイレクト追従 / --retry: ネットワーク一時エラー時のリトライ
HTTP_STATUS=$(curl -s -S -L \
-w "%{http_code}" \
-o "$TMP_RES" \
--max-time "${TIMEOUT_SEC}" \
--retry "${RETRY_COUNT}" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Accept: application/json" \
"${API_URL}")
# 2. HTTPステータスコードの検証
if [ "$HTTP_STATUS" -ne 200 ]; then
echo "[ERROR] API request failed with status: ${HTTP_STATUS}" >&2
cat "$TMP_RES" >&2
exit 1
fi
# 3. jqによるペイロード検証(例:statusが'ok'かつ、data配列が空でないこと)
# -e: フィルター結果が false/null の場合に終了ステータス 1 を返す
if ! jq -e '.status == "ok" and (.data | length > 0)' "$TMP_RES" > /dev/null; then
echo "[ERROR] Invalid API response schema or empty data." >&2
echo "Response: $(cat "$TMP_RES")" >&2
exit 1
fi
echo "[INFO] API validation successful."
systemdによる定期実行設定 (Timer)
/etc/systemd/system/api-checker.service
[Unit] Description=API Health Checker After=network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/api-checker.sh EnvironmentFile=/etc/default/api-checker User=monitoring-user
/etc/systemd/system/api-checker.timer
[Unit] Description=Run API Checker every 5 minutes [Timer] OnCalendar=*:0/5 Persistent=true [Install] WantedBy=timers.target
【検証と運用】
正常系の確認
スクリプトを直接実行し、終了コードを確認します。
./api-checker.sh echo $? # 0であれば正常
異常系のログ確認
systemd経由で実行している場合、journalctl を使用してエラー出力を確認します。
# 特定のサービスのエラーログを直近10件表示 journalctl -u api-checker.service -n 10 --no-pager
【トラブルシューティングと落とし穴】
秘密情報の漏洩: APIトークンをスクリプトに直書きせず、
EnvironmentFileまたはシークレットマネージャー(AWS Secrets Manager等)から読み込んでください。パイプラインの罠:
set -o pipefailがないと、curl ... | jqの構成で curl が失敗しても jq が(空入力に対して)成功判定を出してしまうリスクがあります。ゾンビ一時ファイル:
trapコマンドによるクリーンアップを忘れると、/tmp領域を圧迫します。特に高頻度な定期実行時は注意が必要です。jqのバージョン差異: 古いOS(CentOS 7等)の
jq1.5では一部の演算子が異なる場合があるため、ポータブルな記述(例:length > 0)を優先してください。
【まとめ】
運用の冪等性を維持するための3つのポイント:
ステータスとコンテンツの二段構え検証: HTTP 200を過信せず、必ず
jqで期待するキーの存在をチェックする。リトライ戦略の実装: 一時的なネットワーク瞬断による偽陽性(False Positive)を防ぐため、
curlの--retryオプションを活用する。クリーンアップの徹底:
trapを用いて、実行環境にゴミを残さない設計を徹底する。

