OllamaをWatchdogスクリプトで自動復旧させる方法|bashとcronで異常検知・自動再起動・アラート通知を実装する手順

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > ローカルLLM > OllamaをWatchdogスクリプトで自動復旧させる方法|bashとcronで異常検知・自動再起動・アラート通知を実装する手順
「Ollamaを本番サーバーで動かしているが、夜間に止まっていることが数回あった」
「systemdのRestart=alwaysで再起動はされるが、プロセスは生きているのにAPIが応答しない状態で止まることがある」

そんな経験を持つインフラ担当者は少なくない。systemdやDockerのrestartポリシーはプロセスの生死を管理できるが、「プロセスは稼働しているがAPIが応答しない」という半死状態には対応できない。
この記事では、OllamaのAPI応答を直接確認するWatchdogスクリプトをbashで実装し、cronで定期実行する手順を解説する。再起動後の確認・Slackウェブフック通知・多段エスカレーションまで含めた実践的な構成だ。Ubuntu ServerへのローカルLLM構築が完了している前提で進める。

この記事のポイント

・curl --max-timeでAPIタイムアウトを検出し、プロセス死活だけでなく応答不能状態も復旧する
・systemctl restart / docker restartを自動判定付きで実行し、復旧確認まで自動で行う
・Slackウェブフックとlogrotateの二重設定で24時間無人運用に対応する
・再起動回数を記録してフラッピング検出と管理者エスカレーションを実装する


OllamaをWatchdogスクリプトで自動復旧させる方法|bashとcronで異常検知・自動再起動・アラート通知を実装する手順

「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

OllamaのWatchdogが必要になるケースと自動復旧の設計方針

systemdの`Restart=always`やDockerの`restart: unless-stopped`は、プロセスが**終了した**場合に再起動を試みる仕組みだ。しかし、以下のケースではこれらだけでは不十分なことがある。

典型的なケースとして、Ollamaプロセスは稼働しているのにAPIへのリクエストが応答しなくなる状況がある。GPUのデッドロック・メモリリーク・ロードしたモデルの破損などが原因として考えられる。この状態ではsystemdやDockerからはプロセス正常と判定され、自動再起動が走らない。

Watchdogスクリプトはこの隙間を埋める。APIエンドポイントに実際にHTTPリクエストを送り、応答を確認する。タイムアウト・異常レスポンスを検出したら再起動をかけ、成功・失敗を問わず担当者へ通知する設計だ。

本記事で構築するWatchdogの構成は次の通りだ。

・ヘルスチェック: curlでOllama APIに接続確認(タイムアウト検出含む)
・再起動: systemdとDocker両対応(環境に応じて自動判定)
・通知: Slackウェブフック通知
・エスカレーション: 1時間以内に3回再起動→再起動を停止して管理者へ通知
・ロック: 多重実行防止のロックファイル実装
・ログ: /var/log/ollama-watchdog.log にタイムスタンプ付きで記録

ヘルスチェックスクリプトを作成する

1. スクリプト配置ディレクトリの準備

# Watchdogスクリプト用ディレクトリを作成する $ sudo mkdir -p /opt/ollama-watchdog $ sudo chown $(whoami):$(whoami) /opt/ollama-watchdog $ ls -la /opt/ollama-watchdog/ total 8 drwxr-xr-x 2 ubuntu ubuntu 4096 Nov 4 10:00 . drwxr-xr-x 8 root root 4096 Nov 4 10:00 ..

2. ヘルスチェック関数の実装

ヘルスチェックの核心は、`/api/tags`エンドポイントへのHTTPリクエストだ。HTTPステータスコードだけでなく、レスポンスボディにJSONが返ってきているかまで確認する。

#!/bin/bash # /opt/ollama-watchdog/ollama-watchdog.sh OLLAMA_HOST="http://localhost:11434" LOG_FILE="/var/log/ollama-watchdog.log" RESTART_COUNT_FILE="/tmp/ollama-restart-count" LOCK_FILE="/tmp/ollama-watchdog.lock" MAX_RESTARTS=3 RESTART_WINDOW=3600 log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE" } check_health() { local http_code http_code=$(curl -s --max-time 10 -o /tmp/ollama-health-response \ -w "%{http_code}" "${OLLAMA_HOST}/api/tags" 2>/dev/null) if [ "$http_code" != "200" ]; then log "WARN: API returned HTTP ${http_code} (expected 200)" return 1 fi if ! python3 -c "import json,sys; json.load(sys.stdin)" \ < /tmp/ollama-health-response 2>/dev/null; then log "WARN: API response is not valid JSON" return 1 fi return 0 }

3. ヘルスチェックのみ動作確認

スクリプト作成後、ヘルスチェック部分を単体でテストする。Ollamaが稼働中であれば`HTTP_STATUS: 200`が返る。

# curlでOllama APIの応答を直接確認する $ curl -s --max-time 10 -w "\nHTTP_STATUS: %{http_code}\n" \ http://localhost:11434/api/tags {"models":[{"name":"llama3.3:8b-instruct-q4_K_M","model":"llama3.3:8b-instruct-q4_K_M","modified_at":"...","size":4920753664}]} HTTP_STATUS: 200

`200`が返ればAPI正常だ。タイムアウトやHTTPエラーの場合は次のステップの再起動ロジックが走る。

systemd・Docker両対応の自動再起動ロジックを実装する

1. 管理方式の自動判定ロジック

Ollamaがsystemdで管理されているかDockerで管理されているかを判定する関数を実装する。両方に対応しておくと、サーバーの運用方針変更時にWatchdogを修正せずに済む。

# 管理方式の判定(ollama-watchdog.shに追記する) detect_manager() { if systemctl is-active --quiet ollama 2>/dev/null; then echo "systemd" elif docker inspect ollama --format '{{.State.Status}}' \ 2>/dev/null | grep -q "running"; then echo "docker" else echo "unknown" fi } restart_ollama() { local manager manager=$(detect_manager) log "INFO: Detected manager: ${manager}" case "$manager" in systemd) log "INFO: Restarting via systemctl..." sudo systemctl restart ollama ;; docker) log "INFO: Restarting via docker restart..." docker restart ollama ;; *) log "ERROR: Cannot detect Ollama manager. Manual intervention required." return 1 ;; esac }

2. 再起動後の復旧確認ロジック

再起動直後にヘルスチェックを実行しても起動途中で失敗することがある。起動完了を待つ関数を追加する。

# 起動完了待機ロジック(60秒タイムアウト・5秒間隔で確認) wait_for_recovery() { local max_wait=60 local elapsed=0 local interval=5 log "INFO: Waiting for Ollama to become healthy (max ${max_wait}s)..." while [ $elapsed -lt $max_wait ]; do sleep $interval elapsed=$((elapsed + interval)) if check_health; then log "INFO: Recovery confirmed after ${elapsed}s" return 0 fi log "INFO: Still waiting... (${elapsed}s elapsed)" done log "ERROR: Recovery failed after ${max_wait}s" return 1 }

3. sudoers設定(非rootユーザー用)

cronをrootユーザーで実行しない場合、`systemctl restart ollama`にsudo権限が必要だ。

# /etc/sudoers.d/ollama-watchdogをvisudoで作成する $ sudo visudo -f /etc/sudoers.d/ollama-watchdog # 以下を追加する(usernameは実際の実行ユーザー名に変える) username ALL=(root) NOPASSWD: /usr/bin/systemctl restart ollama username ALL=(root) NOPASSWD: /usr/bin/touch /var/log/ollama-watchdog.log username ALL=(root) NOPASSWD: /usr/bin/chmod 644 /var/log/ollama-watchdog.log

【注意】NOPASSWD設定の範囲を必ず限定すること。`/usr/bin/systemctl`全体にNOPASSWDを付けると、そのユーザーがあらゆるsystemctlコマンドをroot権限で実行できてしまう。上記のように`systemctl restart ollama`の1コマンドだけに絞るのが安全だ。

社内でのローカルLLM導入判断については社内でChatGPTが使えないときの代替手段も参考にしてほしい。

Slackウェブフックでアラート通知とフラッピング検出を実装する

1. Slack通知関数の実装

SlackのIncoming Webhookを使ってアラートを送る。事前にSlackのアプリ管理画面でIncoming Webhookを有効にし、URLを取得しておく必要がある。

# Slack通知関数(ollama-watchdog.shに追記する) SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:-}" send_slack_notification() { local message="$1" local color="${2:-danger}" [ -z "$SLACK_WEBHOOK_URL" ] && return 0 local payload payload=$(printf '{"attachments":[{"color":"%s","text":"%s","footer":"Ollama Watchdog @ %s"}]}' \ "$color" "$message" "$(hostname)") curl -s -X POST -H 'Content-type: application/json' \ --data "$payload" "$SLACK_WEBHOOK_URL" > /dev/null }

2. フラッピング検出ロジックの実装

短時間に繰り返し再起動が走る「フラッピング」状態では、単純な再起動ループに入るリスクがある。再起動回数を記録し、一定回数を超えたら再起動を停止して管理者に通知する。

# フラッピング検出ロジック check_flapping() { local now now=$(date +%s) local count=0 local last_reset=$now if [ -f "$RESTART_COUNT_FILE" ]; then last_reset=$(awk '{print $1}' "$RESTART_COUNT_FILE") count=$(awk '{print $2}' "$RESTART_COUNT_FILE") # ウィンドウ(1時間)をリセットする if [ $((now - last_reset)) -gt $RESTART_WINDOW ]; then count=0 last_reset=$now fi fi local new_count=$((count + 1)) echo "$last_reset $new_count" > "$RESTART_COUNT_FILE" if [ $new_count -gt $MAX_RESTARTS ]; then log "CRITICAL: Restart count ${new_count} exceeded ${MAX_RESTARTS} in ${RESTART_WINDOW}s" send_slack_notification \ "CRITICAL: Ollama restart loop on $(hostname). Manual intervention required." \ "danger" return 1 fi return 0 }

3. Webhook動作テスト

# Slackウェブフックの動作確認(URLは実際のものに差し替える) $ curl -s -X POST -H 'Content-type: application/json' \ --data '{"text":"Watchdog test from '"$(hostname)"'"}' \ "https://hooks.slack.com/services/XXXXX/YYYYY/ZZZZZ" ok

`ok`が返ればSlack連携は正常だ。

cronで定期実行を設定する

1. 完成版スクリプトのメイン処理

ここまでの関数を組み合わせて、メイン処理と多重実行防止ロックを実装する。

# メイン処理(ollama-watchdog.shの末尾に追記する) main() { # 多重実行防止ロック if [ -f "$LOCK_FILE" ]; then local pid pid=$(cat "$LOCK_FILE") if kill -0 "$pid" 2>/dev/null; then log "INFO: Another watchdog (PID ${pid}) is running. Exiting." exit 0 fi fi echo $$ > "$LOCK_FILE" trap "rm -f $LOCK_FILE" EXIT sudo touch "$LOG_FILE" 2>/dev/null sudo chmod 644 "$LOG_FILE" 2>/dev/null if check_health; then log "INFO: Ollama is healthy. No action required." exit 0 fi log "WARN: Ollama health check failed. Starting recovery process." send_slack_notification \ "WARNING: Ollama health check failed on $(hostname). Attempting restart..." \ "warning" if ! check_flapping; then log "ERROR: Flapping detected. Skipping restart." exit 1 fi if restart_ollama && wait_for_recovery; then log "INFO: Ollama recovery successful." send_slack_notification \ "OK: Ollama recovered successfully on $(hostname)." \ "good" exit 0 else log "ERROR: Recovery failed. Manual intervention required." send_slack_notification \ "CRITICAL: Ollama recovery FAILED on $(hostname). Manual intervention required." \ "danger" exit 1 fi } main "$@"

2. スクリプトへの実行権限付与

# 実行権限を付与して動作確認する $ chmod +x /opt/ollama-watchdog/ollama-watchdog.sh # 手動実行でヘルスチェックを通す(Ollamaが稼働中) $ /opt/ollama-watchdog/ollama-watchdog.sh 2026-11-04 10:05:00 INFO: Ollama is healthy. No action required.

3. cronジョブの登録

# crontabを編集する(Ollamaを実行するユーザーで実施する) $ crontab -e # 5分ごとにWatchdogを実行する設定を追加する */5 * * * * SLACK_WEBHOOK_URL='https://hooks.slack.com/services/XXX/YYY/ZZZ' \ /opt/ollama-watchdog/ollama-watchdog.sh >> /var/log/ollama-watchdog-cron.log 2>&1 # 設定確認 $ crontab -l */5 * * * * SLACK_WEBHOOK_URL='https://hooks.slack.com/services/...' \ /opt/ollama-watchdog/ollama-watchdog.sh >> /var/log/ollama-watchdog-cron.log 2>&1

cron登録後、5分待ってからログを確認する。正常時は`INFO: Ollama is healthy. No action required.`が記録される。

よくあるトラブルと対処法

1. curlがタイムアウトする前に次のcronジョブが起動してしまう

**症状**: Ollamaが重い処理中だとAPIの応答に10秒以上かかることがある。5分間隔のcronで複数のWatchdogが並走すると、再起動が重複して発生する場合がある。

対処: 上記で実装したロックファイル機能が多重実行を防ぐ。ロックファイルが残ったまま(Watchdogがクラッシュ等)の場合は手動で削除する。

# ロックファイルが残っている場合は削除する $ ls -la /tmp/ollama-watchdog.lock -rw-r--r-- 1 ubuntu ubuntu 5 Nov 4 10:00 /tmp/ollama-watchdog.lock $ cat /tmp/ollama-watchdog.lock 12345 # そのPIDが存在しないなら削除して良い $ kill -0 12345 2>/dev/null || echo "PID not running, safe to remove" PID not running, safe to remove $ rm /tmp/ollama-watchdog.lock

2. Slack通知が届かない

**症状**: Ollamaが再起動されたがSlackに通知が来ない。

確認手順: Webhook URLを直接curlでテストする。`ok`が返れば接続は正常だ。エラーが出る場合はSlackアプリの設定(Webhook有効化・チャンネル指定)を再確認する。

crontab上でWebhook URLを渡す場合、URLにシングルクォートを使うと`&`が解釈されずに済む。

3. logrotateでWatchdogログを管理する

# /etc/logrotate.d/ollama-watchdog に設定する $ sudo tee /etc/logrotate.d/ollama-watchdog << 'CONF' /var/log/ollama-watchdog.log { weekly rotate 4 compress missingok notifempty create 644 root root } CONF # logrotateの設定テスト(--debug でdry-run確認) $ sudo logrotate --debug /etc/logrotate.d/ollama-watchdog reading config file /etc/logrotate.d/ollama-watchdog Allocating hash table... ...

OllamaのモデルAPIとパラメータ設定についてはUbuntu ServerでのローカルLLM構築基礎もあわせて確認してほしい。

まとめ

OllamaのWatchdogスクリプトについて、ヘルスチェックから通知・エスカレーションまでを実装した。systemdやDockerのrestartポリシーでは補えない「APIが応答しない半死状態」を検知して自動復旧できる体制が整う。主要な設定をまとめると以下の通りだ。
実装項目実装方法主要コマンド・パラメータ
ヘルスチェックcurlでAPIエンドポイントを直接確認curl -s --max-time 10 http://localhost:11434/api/tags
管理方式判定systemctlとdocker inspectで自動判定systemctl is-active ollama / docker inspect ollama
自動再起動管理方式に応じてrestart実行sudo systemctl restart ollama / docker restart ollama
復旧確認60秒間ヘルスチェックを繰り返す5秒間隔×12回
アラート通知Slackウェブフックcurl -X POST -H 'Content-type: application/json'
フラッピング防止1時間内の再起動回数を記録MAX_RESTARTS=3 / RESTART_WINDOW=3600
多重実行防止ロックファイル/tmp/ollama-watchdog.lock
定期実行cronで5分間隔*/5 * * * *
フラッピング検出を入れることで、無限再起動ループによる二次障害も防げる。本番運用では通知先を複数用意して監視の死角をなくすことを推奨する。

OllamaのLinux本番運用スキルを2日間のハンズオンで習得する

WatchdogスクリプトからGPU環境でのOllama本番デプロイまで、実機GPU環境で手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。

>> ローカルAIマスターセミナーの詳細を確認する
ローカルLLMの構築・運用に関する関連記事もあわせて参考にしてください。

・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。