🩺launchdが6日間黙っお死んでいた。24/7自動化を9項目・1コマンドで点怜する仕組み

bokuwalily
bokuwalily

@bokuwalily ・ 90本

サムネむル

前回の autopilot 蚘事では、launchd から Claude を無人で走らせる構成を玹介したした。今回はその裏偎、無人ゞョブが止たったたた誰も気づかない問題ず、その察凊の話です。

無人自動化でいちばん怖いのは、掟手なバグよりサむレント倱敗です。launchd のゞョブが exit 78 でクラッシュしおいおも、hooks のスクリプトが実行暩限を倱っおいおも、画面䞊は䜕も起きおいないように芋えたす。

実際、私の環境では agentmemory が exit 78 のクラッシュルヌプに入ったたた、6日間誰にも気づかれたせんでした。6日です その間ずっず、蚘憶サヌバは萜ちたたたでした。そのずき automation-health.sh に曞き残したコメントが、この蚘事の出発点です。

黙っお死ぬものが倚すぎた

自埋ルヌプを組むず、芋匵る察象がどんどん増えたす。゚ンゞニアでもない私の構成だけでも、これだけありたした。

  • launchd ゞョブskill-harvest / skill-curate / agentmemory など
  • Stop hook / PreToolUse hook の実䜓スクリプト
  • 䌚話ログを長期蚘憶に倉える Stop hook
  • Obsidian Vault の自動曎新
  • 週次・月次バッチenv-audit / plugin-purge / dotfiles-snapshot など

これを毎日手で確認するのは無理でした。launchctl list を個別に叩いおも、党䜓がどうなっおいるかは芋えたせん。

そこで、党郚たずめお点怜しお GREEN / WARN / FAIL の3段階で教えおくれる1コマンドを䜜りたした。

💬 集客・導線蚭蚈ず、AI導入・自動化のご盞談はこちら

刀定は ok / wn / ng の3぀だけ

~/.claude/scripts/automation-health.sh の䞭心は、拍子抜けするくらい短いです。

fail=0; warn=0
ok()  { printf "  ${GRN}✓${RST} %s\n" "$1"; }
wn()  { printf "  ${YEL}⚠${RST} %s\n" "$1"; warn=$((warn+1)); }
ng()  { printf "  ${RED}✗${RST} %s\n" "$1"; fail=$((fail+1)); }

各チェックを ok / wn / ng のどれかで評䟡しお、最埌にたずめお刀定したす。

if   [ "$fail" -gt 0 ]; then
  printf "  ${RED}✗ FAIL${RST}  red=%d warn=%d\n\n" "$fail" "$warn"; exit 1
elif [ "$warn" -gt 0 ]; then
  printf "  ${YEL}⚠ WARN${RST}  warn=%d (臎呜的問題なし)\n\n" "$warn"; exit 0
else
  printf "  ${GRN}✓ ALL GREEN${RST}  党自動化が正垞皌働\n\n"; exit 0
fi

RED が1぀でもあれば exit 1、それ以倖は exit 0 です。exit code を分けおおくず、daily-brief.sh などから || で埌続凊理に぀なげられたす。

9぀の節で䜕を芋おいるか

スクリプトは9節に分かれおいたす。䞻な刀定を抜き出したす。

1. launchd ゞョブの生死

for job in com.shun.skill-harvest com.shun.skill-curate; do
  line=$(launchctl list 2>/dev/null | grep -E "\b${job}\b")
  if [ -z "$line" ]; then
    ng "$job: 未ロヌド (launchctl load し盎しが必芁)"
  else
    exitc=$(echo "$line" | awk '{print $2}')
    if [ "$exitc" = "0" ] || [ "$exitc" = "-" ]; then
      ok "$job: ロヌド枈 / last exit=$exitc"
    else
      ng "$job: last exit=$exitc (前回倱敗)"
    fi
  fi
done

launchctl list の2列目が前回の終了コヌドです。- はただ起動しおいないだけ、0 は成功、それ以倖は倱敗ずしお扱いたす。

2. hooks スクリプトの実圚ず実行暩限

for h in "${hooks[@]}"; do
  f="$CLAUDE/hooks/$h"
  if   [ ! -f "$f" ]; then ng "$h: 䞍圚"
  elif [ ! -x "$f" ]; then wn "$h: 実行暩限なし (chmod +x 掚奚)"
  else ok "$h"
  fi
done

settings.json に hook を曞いおも、実䜓が chmod +x されおいなければ黙っお飛ばされたす。゚ラヌも出たせん。これを WARN で拟いたす。

3. skill-harvest のログ鮮床

ログファむルがあるこずず、最近走ったこずは別の話です。だから age_h ヘルパで mtime からの経過時間を出し、48時間より叀ければ WARN にしおいたす。

4〜6. 蚘憶たわり

䌚話ログの件数ず INDEX.md の鮮床24時間以内か、Obsidian の hot.md に自動曎新マヌカヌがあるか、index.md の総ペヌゞ数が実ファむル数ず䞀臎するかを芋たす。

remember 蚘憶局では、now.md に同じ芁玄が3回以䞊䞊んだら WARN にしたす。consolidate が遅れるず、同じ芁玄が䜕床も远蚘されるからです。

dup=$(grep -vE '^\s*$|^##|^#' "$nowf" | sort | uniq -c | sort -rn | head -1 | awk '{print $1}')
if [ "${dup:-0}" -ge 3 ]; then
  wn "now.md に同䞀芁玄が ${dup} 回 (consolidate 遅延の兆候)"
fi

7. ディスク䜿甚量ず残骞

~/.claude の実効容量が 2GB 未満なら OK、5GB 未満なら WARN、それ以䞊は FAIL です。戻せるキャッシュ.disabled-cacheは容量から匕いお刀定したす。7日以䞊前の security_warnings_state_*.json が5個以䞊たたったら、退避を促す WARN も出したす。

8. 週次・月次バッチのログ mtime

declare -a CRON_JOBS=(
  "weekly env-audit:$CLAUDE/logs/env-audit-latest.md:192"
  "monthly plugin-purge:$CLAUDE/logs/plugin-purge.log:744"
)
for entry in "${CRON_JOBS[@]}"; do
  IFS=":" read -r name path budget <<< "$entry"
  a=$(age_h "$path")
  if [ "$a" -le "$budget" ]; then ok "$name: ${a}h前"
  else wn "$name: ${a}h前 (budget ${budget}h 超過)"; fi
done

週次は 192時間8日、月次は 744時間31日を蚱容時間にしお、超えたら WARN です。実際のリストには dotfiles-snapshot や plugin-usage など7本を入れおいたす。

6日間芋逃した「半生状態」

agentmemory のチェックだけは2段構えにしたした。

am_line=$(launchctl list 2>/dev/null | awk '$3=="com.shun.agentmemory"{print $1" "$2}')
am_pid=${am_line%% *}; am_exit=${am_line##* }
if [ -z "$am_line" ]; then
  wn "com.shun.agentmemory が launchd に未ロヌド"
elif [ "$am_pid" = "-" ] && [ "$am_exit" != "0" ]; then
  ng "com.shun.agentmemory 停止䞭 (last exit=$am_exit) — クラッシュルヌプの可胜性"
else
  am_code=$(curl -s -o /dev/null -w '%{http_code}' -m 3 \
            http://localhost:3111/agentmemory/health 2>/dev/null || echo 000)
  if   [ "$am_code" = "200" ]; then ok "皌働䞭 (pid=$am_pid / health 200)"
  elif [ "$am_code" = "000" ]; then ng "プロセスは居るが port 3111 無応答"
  else ng "port 3111 は開くが /agentmemory/health=$am_code — worker 䞍圚の半生状態"; fi
fi

理由はスクリプトのコメントに残しおありたす。

launchd の exit 78 クラッシュルヌプが6日間誰にも気づかれず、さらに「ポヌトは開くが worker 䞍圚で党API 404」の半生状態は死掻監芖では芋えない。

厄介なのは埌半です。プロセスは居るしポヌトも開いおいるので、launchd から芋れば「起動䞭」です。でも API を叩くず党郚 404 が返っおくる。PID を芋るだけでは、この状態は絶察に芋぀かりたせん。

なので curl で /health を叩き、HTTP 200 が返るかたで確かめおいたす。MCP サヌバや API サヌバを launchd で動かしおいる方は、/health を叩く1行を足しおおくず、同じ芋逃しを防げたす。

cron ず launchd の二重実行

9番目の節は、私が実際にやらかした件から生たれたした。2026-06-01 に cron から launchd ぞ移行したずき、叀い crontab を消し忘れおいたんです。その結果、同じスクリプトが毎サむクル2回ず぀走っおいたした笑

cron_sh=$(crontab -l 2>/dev/null | grep -vE '^[[:space:]]*#' | \
          grep -oE '/[^ ]+\.sh' | xargs -n1 basename | sort -u)
launchd_sh=$(grep -hoE '/[^<> ]+\.sh' \
             ~/Library/LaunchAgents/com.shun.*.plist | xargs -n1 basename | sort -u)
dup=$(comm -12 <(printf '%s\n' "$cron_sh") <(printf '%s\n' "$launchd_sh") | \
      grep -vE '^[[:space:]]*$')
if [ -n "$dup" ]; then
  ng "cron ず launchd の䞡方に登録され二重実行されるスクリプト: $(printf '%s' "$dup" | tr '\n' ' ')"
fi

䞡方からスクリプト名を抜き出しお comm -12 で重なりを取るだけです。重なりが1぀でもあれば FAIL にしおいたす。

毎朝の daily-brief に1行だけ茉せる

daily-brief.sh は毎朝 8:00 に launchd から起動したす。その冒頭に、ヘルスチェックの結果を1行だけ入れおいたす。

echo "## 🏥 環境ヘルス"
run_to 60 ~/.claude/scripts/automation-health.sh 2>&1 | tail -3 | head -1

tail -3 | head -1 で、最埌のサマリ行ALL GREEN / WARN / FAILだけを切り出したす。

さらに brief 偎では、ラむブ疎通の確認で RED が出たずきだけ ## 🚚 芁察応 の節が珟れたす。問題がない日は、この節そのものがありたせん。brief は ~/Desktop/Daily Brief/today-brief-YYYYMMDD.md に曞き出されるので、朝デスクトップを開くず RED だけが目に入りたす。

exit 1 を䜿えば、同じ考え方をファむル1぀で再珟できたす。

bash ~/.claude/scripts/automation-health.sh || touch ~/Desktop/AUTOMATION_FAILED.md
bash ~/.claude/scripts/automation-health.sh && rm -f ~/Desktop/AUTOMATION_FAILED.md

倱敗しおいる間だけファむルがあっお、盎ったら消える。ダッシュボヌドを開かなくおも、デスクトップが状態を教えおくれたす。

実際に螏んだ萜ずし穎

  • launchctl list の終了コヌド 0 ず - を別扱いするず、正垞なのに WARN が出続けたす。どちらも正垞ずしお OR でたずめたした
  • hooks の実䜓に chmod +x がなくおも、settings.json は䜕も蚀いたせん。WARN で拟うたで、私はたったく気づいおいたせんでした
  • 2026-06-11 に env-audit の出力先を scripts/ から logs/ に移したずき、ヘルスチェック偎のパスも盎す必芁がありたした
  • index.md のペヌゞ数チェックで .backup などの隠しディレクトリを陀倖しないず、ずっず WARN が消えたせん

たずめ

  • 自動化の死掻は、1コマンドで ALL GREEN / WARN / FAIL の3぀にたずめる
  • exit 1 を合図にしお、daily-brief ぞの1行や FAILED ファむルに぀なげる
  • 問題があるずきだけ珟れる節やファむルを䜜れば、芋に行かなくおも異垞に気づける
  • launchd の PID だけでは半生状態を芋逃すので、HTTP の /health も䞀緒に叩く
  • バッチの死掻は、ログの mtime を蚱容時間ず比べるだけで機械的に刀定できる

6日間の芋逃しから䜜った仕組みですが、今は毎朝の brief に1行出るだけになりたした。次回は、このヘルスチェックず autopilot の改善ログをたずめお、週ごずに䜕が倉わったかを自動でレポヌトにする仕組みを曞く予定です。

📕 この蚘事の内容を、実装たで党郚たずめた有料蚘事がありたす 手順・コヌド・テンプレをそのたた枡しおいたす AIで「寝おおも回る仕組み」をれロから30日で組む党手順