ID: SRE_CURL_JQ_HANDLING VER: 1.0 AUTH: SRE_AUTO_ENG TAG: REST_API, AUTOMATION, CURL, JQ, ERROR_HANDLING
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
curlとjqによるAPI自動実行の堅牢化:レスポンス検証と例外処理の実践
【導入と前提】
API経由のインフラ操作や状態監視をシェルスクリプトで自動化し、HTTPエラーや期待しないJSONペイロードを検知して安全に異常終了させる手法を解説します。
OS: GNU/Linux (Ubuntu 22.04 / RHEL 9 等)
ツール:
curl(7.70.0以上推奨),jq(1.6以上)
【処理フローと設計】
graph TD
A["開始"] --> B{"curl実行"}
B -->|HTTP 2xx以外| C["異常終了/リトライ"]
B -->|HTTP 2xx| D["jqによるJSON検証"]
D -->|パース失敗/特定キー不在| E["異常終了"]
D -->|検証成功| F["後続処理実行"]
F --> G["終了"]
curlでHTTPレイヤーの成功を担保した後、jqの-e(exit status反映)オプションを用いてアプリケーションレイヤーの値を検証します。パイプラインの途中で失敗した場合、set -o pipefailによりスクリプト全体が停止するように設計します。
【実装:堅牢な自動化スクリプト】
1. API検証スクリプト (api_check.sh)
#!/usr/bin/env bash
# -e: エラーで即停止, -u: 未定義変数参照で停止, -o pipefail: パイプ途中のエラーを拾う
set -euo pipefail
# 終了時に一時ファイルを確実に削除
readonly TMP_RES=$(mktemp)
trap 'rm -f "$TMP_RES"' EXIT
# 設定項目(環境変数からの取得を推奨)
API_ENDPOINT="${API_ENDPOINT:-https://api.example.com/v1/status}"
AUTH_TOKEN="${AUTH_TOKEN:-default_token}"
echo "Checking API status..."
# curlの実行
# -s: 進捗非表示, -S: エラー時のみ表示, -f: HTTP 4xx/5xxでエラー終了
# -L: リダイレクト追従, --retry: 一時的エラー時の再試行
# -w: レスポンスコードを標準出力の最後に付与
HTTP_CODE=$(curl -sSfL \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "Accept: application/json" \
--retry 3 \
--retry-delay 2 \
-w "%{http_code}" \
-o "$TMP_RES" \
"$API_ENDPOINT")
# HTTPステータスコードの検証
if [ "$HTTP_CODE" -ne 200 ]; then
echo "Error: Unexpected HTTP status $HTTP_CODE" >&2
exit 1
fi
# jqによるJSON内容の検証
# -e: フィルタの結果がnullまたはfalseの場合に終了コード1を返す
# .status == "healthy" を検証
if ! jq -e '.status == "healthy"' "$TMP_RES" > /dev/null; then
echo "Error: API status is not healthy." >&2
cat "$TMP_RES" >&2
exit 2
fi
# 必要な値の抽出(-r: クォートなし出力)
VERSION=$(jq -r '.version' "$TMP_RES")
echo "Success: System version $VERSION is healthy."
2. 定期実行の設定 (systemd timer)
# /etc/systemd/system/api-health-check.service [Unit] Description=API Health Check Service [Service] Type=oneshot ExecStart=/usr/local/bin/api_check.sh Environment="API_ENDPOINT=https://api.example.com/health" EnvironmentFile=/etc/default/api-credentials # トークン等を隔離保存 User=monitoring-user # /etc/systemd/system/api-health-check.timer [Unit] Description=Run API Health Check every 5 minutes [Timer] OnCalendar=*:0/5 Persistent=true [Install] WantedBy=timers.target
【検証と運用】
正常系の確認
スクリプトを手動実行し、終了ステータスが 0 であることを確認します。
./api_check.sh echo $? # 0が返れば正常
異常系のログ確認
systemdで実行している場合、journalctlを用いて詳細なエラー原因(curlの終了コードやjqの検証失敗メッセージ)を追跡します。
# 失敗した直近のログを確認 journalctl -u api-health-check.service -n 50 --no-pager
【トラブルシューティングと落とし穴】
トークンの露出防止: スクリプト内に直接トークンを書かず、
EnvironmentFileや秘密情報管理ツール(Vault等)から読み込んでください。psコマンドで見えないよう配慮が必要です。jqのバージョン差異: 古い環境(jq 1.5未満)では
-eオプションの挙動が一部異なる場合があります。可能な限り最新のバイナリを配置してください。巨大なJSONレスポンス: 数MBを超えるJSONを処理する場合、
jqのメモリ消費が増大します。ストリーム処理(jq --stream)の検討が必要ですが、通常のAPIレスポンスなら逐次処理で十分です。プロキシ設定: 企業内ネットワークでは
http_proxy環境変数の影響を受けます。--noproxyオプションや環境変数のunsetを適宜組み合わせてください。
【まとめ】
運用の冪等性を維持するための3つのポイント:
HTTPレイヤーとContentレイヤーの二段階検証:
curl -fだけでなくjq -eで中身まで保証する。シェルオプションの厳格化:
set -euo pipefailを定型句として埋め込み、連鎖的なエラーを見逃さない。一時ファイル管理の自動化:
trapコマンドを使用し、異常終了時でもゴミを残さない設計にする。

