◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-07-18上級

headless の Claude Code を止めたのに、ビルドだけが生き残っていた — exit 143 を前提に停止処理を設計する

headless モードの Claude Code が Bash 実行中に SIGTERM を受けると、コマンドのプロセスツリーが孤児化していました。2.1.212 の修正で挙動は exit 143 に変わります。この契約を前提に、監督スクリプトと後片づけを設計し直す手順をまとめます。

Claude Code265headless13SIGTERM自動運用17プロセス管理

✦ プレミアム記事

夜間に回していた個人開発のメンテナンス処理を、朝になって手動で止めたときのことでした。systemctl stop を打って、プロンプトはすぐ戻ってきました。ところが数時間後、VM のディスク使用率のアラートが飛んできます。調べると、止めたはずのジョブが起動していた next build のプロセスが一つ、CPU をつかんだまま生き残っていました。親は消えているのに、子だけが動き続けている。ポートも握ったままで、次のセッションが同じポートで立ち上がらずに失敗していました。

停止コマンドは成功していました。失敗していたのは、その停止が子プロセスまで届いていなかったことです。以下では、headless(-p / SDK)モードの Claude Code が Bash 実行中に停止されたときに何が起きていたのか、Claude Code 2.1.212 の修正でそれがどう変わったのか、そして新しい exit 143 という契約を前提に監督側と後片づけをどう組み直すかを、実際に踏んだ順序で書いていきます。

停止したはずのジョブが、CPU を食い続けていた

まず、何が孤児になっていたのかを整理します。headless の Claude Code は、Bash ツールを呼ぶときに子プロセスとしてシェルを起動します。そのシェルがさらに npm run build を起動し、build が別のワーカーを起動する。ツリーは深くなります。

層プロセス役割
親claude(headless)ターンを回し、ツールを呼ぶ
子bash -cツール実行のシェル
孫npm / nodeビルドやテストの本体
ひ孫worker スレッド群実際に CPU を使う

systemctl stop や timeout が送るのは、既定では親プロセスへの SIGTERM です。親の claude はシグナルを受けてターンを畳もうとします。問題は、そのとき親が子のツリーを明示的に終わらせないまま先に抜けてしまうと、孫・ひ孫が親を失った孤児(orphan)として init(PID 1)に引き取られ、そのまま走り続けることでした。ビルドは止まらず、ポートは解放されず、テンポラリの中間ファイルはディスクを埋め続けます。

私が踏んだのはまさにこれで、しかも厄介なのは「停止コマンドの終了コードは 0 だった」ことです。監督している側からは、成功したように見えていました。本番運用でこの落とし穴に一度ハマると、原因の切り分けに時間を取られます。対処の第一歩は、まず何が孤児として残るのかを正確に知ることでした。

なぜ孤児化するのか — シグナルはプロセスグループには自動で届かない

ここは Claude Code に限らない Unix の話ですが、原因の核心なので押さえておきます。kill <pid> や既定の SIGTERM は、指定した単一の PID にしか届きません。子孫プロセスへは自動的には伝播しません。

伝播させるには二つの道があります。一つはプロセスグループ全体へ送る方法で、kill -TERM -<pgid>(PID の前にマイナスを付けるとプロセスグループ ID として解釈されます)を使います。もう一つは、親プロセス自身が SIGTERM を受け取ったハンドラの中で、自分の子孫を辿って明示的に終わらせてから抜ける方法です。

修正前の headless Claude Code は、Bash 実行中に停止されたケースで、この「抜ける前に子孫を片づける」処理が抜けていました。親は行儀よく終了するのに、孫は取り残される。だからこそ、監督スクリプト側で KillMode を握っていなかった環境では、孤児が素通りしていたわけです。

送り方届く範囲孫プロセス
kill -TERM <pid>その PID のみ取り残される可能性
kill -TERM -<pgid>プロセスグループ全体まとめて届く
親がハンドラで子孫を kill親が辿った範囲親の実装しだい
✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦SIGTERM がプロセスグループに届かず孤児が残る仕組みと、2.1.212 で入った中断・kill・exit 143 の契約
✦timeout と systemd の監督側を exit 143 前提で書き直す Before/After のコード
✦孤児が出ていたかを事後に確かめる検証手順と、SessionEnd フックが担う後片づけとの分担
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⟐ Claude Code2026-10-15
日本語フォルダ名を守るはずのフックが、一度も止めてくれませんでした — Python の stdin が cp932 で読んでいた話
「経理」「議事録」などの日本語フォルダを守る PreToolUse フックが、Python の stdin 既定が cp932 の環境では素通りします。再現の手順と 3 行の直し方、確認用の 1 コマンドを書き残します。
⟐ Claude Code2026-10-14
onFailure を block にしても、jq が無い環境では公式例の rm -rf ブロックは素通りしました
PreToolUse の門番フックは、落ちたときに通すのか止めるのか。公式例を jq の無い環境で走らせると exit 0 で素通りしました。終了コード10通りの実測、直し方、settings.json を走査して素通りを洗い出すスクリプトをまとめます。
⟐ Claude Code2026-10-14
Grep の先頭250行は、一致した183ファイルのうち42ファイルしか見ていませんでした
記事リポジトリで「hook」を探したところ、一致は1,312行・183ファイル。ripgrep・git grep・grep の速さは11〜35 msで差がなく、効いたのは出力の量と順番でした。先頭250行の取りこぼしを事前に見積もるスクリプトと、探索の順番を実測値つきでまとめます。