<p><style_prompt>
{
“role”: “SRE/DevOps Engineer”,
“style”: “Technical, Practical, Robust, Explanatory”,
“formatting”: “Markdown with Mermaid, Code blocks with comments”,
“language”: “Japanese”
}
</style_prompt></p>
<p>本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">curlとjqを用いたREST API監視スクリプトの堅牢な自動化設計</h1>
<h2 class="wp-block-heading">【導入と前提】</h2>
<p>APIの死活監視とレスポンスの妥当性検証を自動化し、障害検知時の初動を迅速化するシェルスクリプトのテンプレートを提供します。</p>
<ul class="wp-block-list">
<li><p><strong>前提OS</strong>: Linux (Ubuntu 22.04 LTS / RHEL 9 等)</p></li>
<li><p><strong>必須ツール</strong>: <code>curl</code> (v7.71.0以降推奨), <code>jq</code> (v1.6以降)</p></li>
</ul>
<h2 class="wp-block-heading">【処理フローと設計】</h2>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["開始: 定期実行"] --> B{"curl実行: APIリクエスト"}
B -- HTTP 200以外 --> C["エラーログ出力 & 終了"]
B -- HTTP 200 --> D["jq: レスポンス検証"]
D -- スキーマ/値の異常 --> E["警告通知 & 終了"]
D -- 正常 --> F["ステータス更新 & 一時ファイル削除"]
F --> G["終了"]
</pre></div>
<p>このフローでは、HTTPプロトコルレベルの成否判定と、<code>jq</code>によるビジネスロジック(JSONペイロードの中身)の検証を分離し、多段階でエラーをトラップします。</p>
<h2 class="wp-block-heading">【実装:堅牢な自動化スクリプト】</h2>
<h3 class="wp-block-heading">1. 監視実行スクリプト (<code>api_monitor.sh</code>)</h3>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/usr/bin/env bash
# set -e: エラー発生時に即座に終了
# set -u: 未定義変数の参照をエラーとする
# set -o pipefail: パイプ途中のエラーを戻り値に反映させる
set -euo pipefail
# 設定項目
API_URL="https://api.example.com/v1/health"
TEMP_FILE=$(mktemp /tmp/api_response.XXXXXX.json)
RETRY_COUNT=3
TIMEOUT_SEC=10
# 終了時に一時ファイルを確実に削除する
trap 'rm -f "$TEMP_FILE"' EXIT
echo "[INFO] API検証開始: ${API_URL}"
# 1. curlによるデータ取得
# -s: 進捗非表示, -S: エラー表示, -L: リダイレクト追従
# -f: HTTPエラー(4xx/5xx)時に異常終了させる
# --retry: ネットワーク一時不全に対するリトライ
if ! curl -sSLf \
--connect-timeout "$TIMEOUT_SEC" \
--retry "$RETRY_COUNT" \
--retry-delay 2 \
-o "$TEMP_FILE" \
"$API_URL"; then
echo "[ERROR] APIへの接続に失敗しました、またはHTTPステータスエラーです。" >&2
exit 1
fi
# 2. jqによるJSONペイロードの検証
# .status が "UP" かどうかをチェック
# jq -e は結果が false または null の場合に終了コード 1 を返す
if ! jq -e '.status == "UP"' "$TEMP_FILE" > /dev/null; then
echo "[ERROR] APIステータスが 'UP' ではありません。" >&2
echo "レスポンス内容: $(cat "$TEMP_FILE")" >&2
exit 1
fi
# 3. 特定の値の抽出例(例: バージョン情報の記録)
VERSION=$(jq -r '.version // "unknown"' "$TEMP_FILE")
echo "[SUCCESS] APIは健全です (Version: ${VERSION})"
</pre>
</div>
<h3 class="wp-block-heading">2. systemdによる定期実行設定</h3>
<p><code>/etc/systemd/system/api-check.service</code> (サービス定義)</p>
<div class="codehilite">
<pre data-enlighter-language="generic">[Unit]
Description=API Health Check Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/api_monitor.sh
User=monitor-user
Group=monitor-user
[Install]
WantedBy=multi-user.target
</pre>
</div>
<p><code>/etc/systemd/system/api-check.timer</code> (タイマー定義: 5分ごと)</p>
<div class="codehilite">
<pre data-enlighter-language="generic">[Unit]
Description=Run API Health Check every 5 minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
</pre>
</div>
<h2 class="wp-block-heading">【検証と運用】</h2>
<h3 class="wp-block-heading">正常系の確認</h3>
<p>スクリプトを手動実行し、標準出力に <code>[SUCCESS]</code> が表示されること、および終了コードが <code>0</code> であることを確認します。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">bash api_monitor.sh
echo $?
</pre>
</div>
<h3 class="wp-block-heading">異常系の確認(ログ確認)</h3>
<p><code>systemd</code> 経由で実行した場合、エラーログは <code>journalctl</code> で集約管理されます。</p>
<div class="codehilite">
<pre data-enlighter-language="generic"># 特定のサービスのエラーログを直近1時間分表示
journalctl -u api-check.service --since "1 hour ago"
</pre>
</div>
<h2 class="wp-block-heading">【トラブルシューティングと落とし穴】</h2>
<ol class="wp-block-list">
<li><p><strong>権限問題</strong>:
<code>mktemp</code> で作成するディレクトリ(<code>/tmp</code>)に、実行ユーザーの書き込み権限があるか確認してください。<code>systemd</code> で実行する場合は <code>User=</code> に指定したユーザーの権限が適用されます。</p></li>
<li><p><strong>環境変数の漏洩</strong>:
APIキーなどをスクリプトに直書きせず、<code>systemd</code> の <code>EnvironmentFile=</code> や、Vault等の外部管理ツールから読み込むように設計してください。</p></li>
<li><p><strong>jqのバージョン差異</strong>:
古い <code>jq</code> (v1.5未満) では一部の演算子の挙動が異なる場合があります。コンテナイメージやOSパッケージのバージョンを固定することを推奨します。</p></li>
</ol>
<h2 class="wp-block-heading">【まとめ】</h2>
<p>運用の冪等性と堅牢性を維持するための3つのポイント:</p>
<ol class="wp-block-list">
<li><p><strong>パイプラインの安全確保</strong>: <code>set -o pipefail</code> を使い、<code>curl</code> の失敗を <code>jq</code> が隠蔽しないようにする。</p></li>
<li><p><strong>リソースのクリーンアップ</strong>: <code>trap</code> コマンドで、スクリプトが異常終了しても一時ファイルが残らないように制御する。</p></li>
<li><p><strong>リトライロジックの内包</strong>: 一時的なネットワークの揺らぎでアラートを発報させないよう、<code>curl</code> 自体のリトライオプションを適切に活用する。</p></li>
</ol>
{
“role”: “SRE/DevOps Engineer”,
“style”: “Technical, Practical, Robust, Explanatory”,
“formatting”: “Markdown with Mermaid, Code blocks with comments”,
“language”: “Japanese”
}
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
curlとjqを用いたREST API監視スクリプトの堅牢な自動化設計
【導入と前提】
APIの死活監視とレスポンスの妥当性検証を自動化し、障害検知時の初動を迅速化するシェルスクリプトのテンプレートを提供します。
【処理フローと設計】
graph TD
A["開始: 定期実行"] --> B{"curl実行: APIリクエスト"}
B -- HTTP 200以外 --> C["エラーログ出力 & 終了"]
B -- HTTP 200 --> D["jq: レスポンス検証"]
D -- スキーマ/値の異常 --> E["警告通知 & 終了"]
D -- 正常 --> F["ステータス更新 & 一時ファイル削除"]
F --> G["終了"]
このフローでは、HTTPプロトコルレベルの成否判定と、jqによるビジネスロジック(JSONペイロードの中身)の検証を分離し、多段階でエラーをトラップします。
【実装:堅牢な自動化スクリプト】
1. 監視実行スクリプト (api_monitor.sh)
#!/usr/bin/env bash
# set -e: エラー発生時に即座に終了
# set -u: 未定義変数の参照をエラーとする
# set -o pipefail: パイプ途中のエラーを戻り値に反映させる
set -euo pipefail
# 設定項目
API_URL="https://api.example.com/v1/health"
TEMP_FILE=$(mktemp /tmp/api_response.XXXXXX.json)
RETRY_COUNT=3
TIMEOUT_SEC=10
# 終了時に一時ファイルを確実に削除する
trap 'rm -f "$TEMP_FILE"' EXIT
echo "[INFO] API検証開始: ${API_URL}"
# 1. curlによるデータ取得
# -s: 進捗非表示, -S: エラー表示, -L: リダイレクト追従
# -f: HTTPエラー(4xx/5xx)時に異常終了させる
# --retry: ネットワーク一時不全に対するリトライ
if ! curl -sSLf \
--connect-timeout "$TIMEOUT_SEC" \
--retry "$RETRY_COUNT" \
--retry-delay 2 \
-o "$TEMP_FILE" \
"$API_URL"; then
echo "[ERROR] APIへの接続に失敗しました、またはHTTPステータスエラーです。" >&2
exit 1
fi
# 2. jqによるJSONペイロードの検証
# .status が "UP" かどうかをチェック
# jq -e は結果が false または null の場合に終了コード 1 を返す
if ! jq -e '.status == "UP"' "$TEMP_FILE" > /dev/null; then
echo "[ERROR] APIステータスが 'UP' ではありません。" >&2
echo "レスポンス内容: $(cat "$TEMP_FILE")" >&2
exit 1
fi
# 3. 特定の値の抽出例(例: バージョン情報の記録)
VERSION=$(jq -r '.version // "unknown"' "$TEMP_FILE")
echo "[SUCCESS] APIは健全です (Version: ${VERSION})"
2. systemdによる定期実行設定
/etc/systemd/system/api-check.service (サービス定義)
[Unit]
Description=API Health Check Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/api_monitor.sh
User=monitor-user
Group=monitor-user
[Install]
WantedBy=multi-user.target
/etc/systemd/system/api-check.timer (タイマー定義: 5分ごと)
[Unit]
Description=Run API Health Check every 5 minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
【検証と運用】
正常系の確認
スクリプトを手動実行し、標準出力に [SUCCESS] が表示されること、および終了コードが 0 であることを確認します。
bash api_monitor.sh
echo $?
異常系の確認(ログ確認)
systemd 経由で実行した場合、エラーログは journalctl で集約管理されます。
# 特定のサービスのエラーログを直近1時間分表示
journalctl -u api-check.service --since "1 hour ago"
【トラブルシューティングと落とし穴】
権限問題:
mktemp で作成するディレクトリ(/tmp)に、実行ユーザーの書き込み権限があるか確認してください。systemd で実行する場合は User= に指定したユーザーの権限が適用されます。
環境変数の漏洩:
APIキーなどをスクリプトに直書きせず、systemd の EnvironmentFile= や、Vault等の外部管理ツールから読み込むように設計してください。
jqのバージョン差異:
古い jq (v1.5未満) では一部の演算子の挙動が異なる場合があります。コンテナイメージやOSパッケージのバージョンを固定することを推奨します。
【まとめ】
運用の冪等性と堅牢性を維持するための3つのポイント:
パイプラインの安全確保: set -o pipefail を使い、curl の失敗を jq が隠蔽しないようにする。
リソースのクリーンアップ: trap コマンドで、スクリプトが異常終了しても一時ファイルが残らないように制御する。
リトライロジックの内包: 一時的なネットワークの揺らぎでアラートを発報させないよう、curl 自体のリトライオプションを適切に活用する。
コメント