<p>本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">REST API監視の自動化:curlとjqによる堅牢なレスポンス検証パイプラインの構築</h1>
<h3 class="wp-block-heading">【導入と前提】</h3>
<p>REST APIの死活監視とデータ整合性を自動検証し、障害検知時の信頼性を高める堅牢なシェルスクリプト運用を実現します。</p>
<ul class="wp-block-list">
<li><p><strong>OS</strong>: Linux (Ubuntu 22.04+, RHEL 8/9等)</p></li>
<li><p><strong>ツール</strong>: <code>curl</code> (7.60+), <code>jq</code> (1.6+)</p></li>
<li><p><strong>権限</strong>: 実行ユーザーに外部ネットワークへの疎通権限があること</p></li>
</ul>
<h3 class="wp-block-heading">【処理フローと設計】</h3>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A[Start] --> B["curl: APIリクエスト実行"]
B --> C{"HTTPステータス確認"}
C -->|200 OK以外| D["リトライ/エラー終了"]
C -->|200 OK| E["jq: JSON構造/値の検証"]
E --> F{"検証成功?"}
F -->|NO| G["エラーログ出力"]
F -->|YES| H["正常終了/後続処理"]
</pre></div>
<p>リクエスト実行からJSONパース、特定フィールドのバリデーションまでをパイプラインで接続し、途中の失敗を即座にトラップする設計をとります。</p>
<h3 class="wp-block-heading">【実装:堅牢な自動化スクリプト】</h3>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/usr/bin/env bash
# --- 設定 ---
set -euo pipefail
# -e: エラー発生時に即座に終了
# -u: 未定義変数の参照時に終了
# -o pipefail: パイプライン途中のエラーも検知
readonly API_URL="${API_URL:-https://api.example.com/v1/health}"
readonly AUTH_TOKEN="${API_TOKEN:-default_token}"
readonly TMP_FILE=$(mktemp /tmp/api_response.XXXXXX)
# --- 終了処理(一時ファイルの削除) ---
trap 'rm -f "$TMP_FILE"' EXIT
echo "[INFO] API検証を開始します: ${API_URL}"
# --- APIリクエストの実行 ---
# -s: サイレントモード
# -S: エラー時はエラーメッセージを表示
# -f: HTTPエラー(4xx/5xx)時に異常終了
# -L: リダイレクトを追跡
# --retry: 通信失敗時のリトライ回数
RESPONSE_CODE=$(curl -sSfL \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "Accept: application/json" \
--retry 3 \
--retry-delay 5 \
-w "%{http_code}" \
-o "$TMP_FILE" \
"$API_URL")
# --- JSONレスポンスの検証 ---
if [ "$RESPONSE_CODE" -eq 200 ]; then
# jqの-e (exit-status) オプションで値の有無を判定
# 例: statusが "ok" かつ service_list が空でないことを確認
if jq -e '.status == "ok" and (.services | length > 0)' "$TMP_FILE" > /dev/null; then
echo "[SUCCESS] APIレスポンスは正常です。"
# 必要なデータを抽出して利用可能
VERSION=$(jq -r '.version' "$TMP_FILE")
echo "[INFO] System Version: ${VERSION}"
else
echo "[ERROR] JSONバリデーションに失敗しました。" >&2
cat "$TMP_FILE" >&2
exit 1
fi
else
echo "[ERROR] 不正なHTTPステータスコード: ${RESPONSE_CODE}" >&2
exit 1
fi
</pre>
</div>
<h4 class="wp-block-heading">systemdによる定期実行例(timerユニット)</h4>
<p><code>/etc/systemd/system/api-check.timer</code> 等で設定することで、安定した定期監視が可能です。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">[Unit]
Description=Run API Health Check every 5 minutes
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
[Install]
WantedBy=timers.target
</pre>
</div>
<h3 class="wp-block-heading">【検証と運用】</h3>
<ol class="wp-block-list">
<li><p><strong>正常系の確認</strong>:
スクリプトを手動実行し、終了コードが <code>0</code> であることを確認します。
<code>bash api_check.sh && echo "OK"</code></p></li>
<li><p><strong>エラー時のログ確認</strong>:
systemd経由で実行している場合、<code>journalctl</code> を使用して標準エラー出力を確認します。
<code>journalctl -u api-check.service -n 50 --no-pager</code></p></li>
<li><p><strong>jqによるフィルタ確認</strong>:
取得した一時ファイルに対し、<code>jq</code> で意図したデータが引けるかテストします。
<code>cat /tmp/api_response.json | jq '.data[0].id'</code></p></li>
</ol>
<h3 class="wp-block-heading">【トラブルシューティングと落とし穴】</h3>
<ul class="wp-block-list">
<li><p><strong>環境変数の漏洩</strong>: APIトークンなどをスクリプト内にハードコードせず、<code>systemd</code> の <code>EnvironmentFile</code> や CI/CDのSecretを使用してください。</p></li>
<li><p><strong>pipefailの重要性</strong>: <code>curl ... | jq ...</code> と繋げた際、<code>pipefail</code> がないと <code>curl</code> が失敗しても <code>jq</code> が動いてしまい、正常終了(Exit 0)として扱われるリスクがあります。</p></li>
<li><p><strong>タイムアウト設定</strong>: デフォルトでは <code>curl</code> はタイムアウトしないことがあるため、<code>--max-time 10</code> などの明示的な指定を検討してください。</p></li>
<li><p><strong>権限問題</strong>: <code>/tmp</code> への書き込み権限や、実行ユーザーの <code>PATH</code> に <code>jq</code> が含まれているかを確認してください。</p></li>
</ul>
<h3 class="wp-block-heading">【まとめ】</h3>
<p>運用の冪等性と堅牢性を維持するための3つのポイント:</p>
<ol class="wp-block-list">
<li><p><strong>異常系の早期リターン</strong>: <code>set -euo pipefail</code> で「沈黙の失敗」を防ぐ。</p></li>
<li><p><strong>型と構造の厳格な検証</strong>: <code>jq</code> の終了コードを活用し、JSONの中身まで踏み込んで検証する。</p></li>
<li><p><strong>副作用の最小化</strong>: <code>trap</code> による一時ファイル削除や環境変数の局所化を徹底する。</p></li>
</ol>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
REST API監視の自動化:curlとjqによる堅牢なレスポンス検証パイプラインの構築
【導入と前提】
REST APIの死活監視とデータ整合性を自動検証し、障害検知時の信頼性を高める堅牢なシェルスクリプト運用を実現します。
OS: Linux (Ubuntu 22.04+, RHEL 8/9等)
ツール: curl (7.60+), jq (1.6+)
権限: 実行ユーザーに外部ネットワークへの疎通権限があること
【処理フローと設計】
graph TD
A[Start] --> B["curl: APIリクエスト実行"]
B --> C{"HTTPステータス確認"}
C -->|200 OK以外| D["リトライ/エラー終了"]
C -->|200 OK| E["jq: JSON構造/値の検証"]
E --> F{"検証成功?"}
F -->|NO| G["エラーログ出力"]
F -->|YES| H["正常終了/後続処理"]
リクエスト実行からJSONパース、特定フィールドのバリデーションまでをパイプラインで接続し、途中の失敗を即座にトラップする設計をとります。
【実装:堅牢な自動化スクリプト】
#!/usr/bin/env bash
# --- 設定 ---
set -euo pipefail
# -e: エラー発生時に即座に終了
# -u: 未定義変数の参照時に終了
# -o pipefail: パイプライン途中のエラーも検知
readonly API_URL="${API_URL:-https://api.example.com/v1/health}"
readonly AUTH_TOKEN="${API_TOKEN:-default_token}"
readonly TMP_FILE=$(mktemp /tmp/api_response.XXXXXX)
# --- 終了処理(一時ファイルの削除) ---
trap 'rm -f "$TMP_FILE"' EXIT
echo "[INFO] API検証を開始します: ${API_URL}"
# --- APIリクエストの実行 ---
# -s: サイレントモード
# -S: エラー時はエラーメッセージを表示
# -f: HTTPエラー(4xx/5xx)時に異常終了
# -L: リダイレクトを追跡
# --retry: 通信失敗時のリトライ回数
RESPONSE_CODE=$(curl -sSfL \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "Accept: application/json" \
--retry 3 \
--retry-delay 5 \
-w "%{http_code}" \
-o "$TMP_FILE" \
"$API_URL")
# --- JSONレスポンスの検証 ---
if [ "$RESPONSE_CODE" -eq 200 ]; then
# jqの-e (exit-status) オプションで値の有無を判定
# 例: statusが "ok" かつ service_list が空でないことを確認
if jq -e '.status == "ok" and (.services | length > 0)' "$TMP_FILE" > /dev/null; then
echo "[SUCCESS] APIレスポンスは正常です。"
# 必要なデータを抽出して利用可能
VERSION=$(jq -r '.version' "$TMP_FILE")
echo "[INFO] System Version: ${VERSION}"
else
echo "[ERROR] JSONバリデーションに失敗しました。" >&2
cat "$TMP_FILE" >&2
exit 1
fi
else
echo "[ERROR] 不正なHTTPステータスコード: ${RESPONSE_CODE}" >&2
exit 1
fi
systemdによる定期実行例(timerユニット)
/etc/systemd/system/api-check.timer 等で設定することで、安定した定期監視が可能です。
[Unit]
Description=Run API Health Check every 5 minutes
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
[Install]
WantedBy=timers.target
【検証と運用】
正常系の確認:
スクリプトを手動実行し、終了コードが 0 であることを確認します。
bash api_check.sh && echo "OK"
エラー時のログ確認:
systemd経由で実行している場合、journalctl を使用して標準エラー出力を確認します。
journalctl -u api-check.service -n 50 --no-pager
jqによるフィルタ確認:
取得した一時ファイルに対し、jq で意図したデータが引けるかテストします。
cat /tmp/api_response.json | jq '.data[0].id'
【トラブルシューティングと落とし穴】
環境変数の漏洩: APIトークンなどをスクリプト内にハードコードせず、systemd の EnvironmentFile や CI/CDのSecretを使用してください。
pipefailの重要性: curl ... | jq ... と繋げた際、pipefail がないと curl が失敗しても jq が動いてしまい、正常終了(Exit 0)として扱われるリスクがあります。
タイムアウト設定: デフォルトでは curl はタイムアウトしないことがあるため、--max-time 10 などの明示的な指定を検討してください。
権限問題: /tmp への書き込み権限や、実行ユーザーの PATH に jq が含まれているかを確認してください。
【まとめ】
運用の冪等性と堅牢性を維持するための3つのポイント:
異常系の早期リターン: set -euo pipefail で「沈黙の失敗」を防ぐ。
型と構造の厳格な検証: jq の終了コードを活用し、JSONの中身まで踏み込んで検証する。
副作用の最小化: trap による一時ファイル削除や環境変数の局所化を徹底する。
ライセンス:本記事のテキスト/コードは特記なき限り
CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。
コメント