「Claude Code に Blender のレンダリングを任せたら、ちょうど2分で殺された」「コマンドに timeout 2400 を付けているのに、なぜか2分で Exit code 143」「cron の SIGTERM と同じ 143 だから、どっちが原因か分からない」。
Claude Code の Bash ツールには、コマンドそのものとは別にツール呼び出しの寿命があり、既定では2分です。コマンド側でどれだけ長い timeout を指定しても、この寿命は延びません。この記事では、症状の見分け方、2分で止まる仕組み、そして10分までと10分超のそれぞれで完走させる手順をまとめます。
Bash ツールの既定タイムアウトは 120,000ms(2分)、上限は 600,000ms(10分)。
コマンド側の
timeout 2400 はコマンドの寿命、ツールの timeout パラメータは呼び出しの寿命。短いほうが勝つ。 2分を超える処理はツール側の
timeout を明示する(例: 300000)。 10分を超えるならバックグラウンド実行に切り替え、ログファイルで完了を待つ。
見分けは「Command timed out after Nm Ns」の一文の有無。cron の 143 にはこの文が無い。
目次を開く
症状: timeout を付けているのに2分で Exit code 143
実際に踏んだのは、Blender をバックグラウンドで本焼きする1行です。コマンド側では40分の timeout を指定していました。
rm -rf out/ && timeout 2400 blender --background --factory-startup \
--python render.py > render.log 2>&1; echo rc=$? Claude Code の返答は次の通りで、コマンドの timeout とは無関係にきっかり2分で止まります。
Exit code 143
Command timed out after 2m 0s 143 は SIGTERM(128 + 15)で終了したことを示す一般的な値です。cron や systemd に殺されたときも同じ数字が出るので、数字だけ見て原因を決めないのが第一歩です。
原因: 寿命が2つあり、短いほうが勝つ
| 寿命 | 誰が決めるか | 既定 | 上限 |
|---|---|---|---|
| コマンドの寿命 | timeout 2400 ... のようにコマンド側で指定 | 無制限 | 無制限 |
| ツール呼び出しの寿命 | Bash ツールの timeout パラメータ(ミリ秒) | 120,000ms(2分) | 600,000ms(10分) |
Claude Code はコマンドを Bash ツール経由で実行し、ツール側の寿命を過ぎるとプロセスに SIGTERM を送って結果を打ち切ります。コマンド側の timeout はその内側で動いているだけなので、外側の2分が先に来れば必ず負けます。timeout を 2400 に伸ばしても、ツールの既定が 120,000ms のままでは何も変わりません。
対処1: 10分以内ならツール側の timeout を明示する
Bash ツールには timeout パラメータがあり、ミリ秒で指定します。Claude に依頼するときは「ツールの timeout を 300000 で実行して」のようにパラメータ側の値を伝えてください。ツール呼び出しはおおむね次の形になります。
{"command": "timeout 2400 blender --background --python render.py > render.log 2>&1; echo rc=$?",
"timeout": 300000} 同じコマンドをこの形で撃ち直したところ、4分かけて rc=0 で完走しました。目安は次の通りです。
| 想定時間 | ツール側 timeout |
|---|---|
| 〜2分 | 指定不要(既定) |
| 2〜5分 | 300000 |
| 5〜10分 | 600000(上限) |
| 10分超 | 対処2へ |
既定値そのものを変えたい場合は、Claude Code の設定で環境変数 BASH_DEFAULT_TIMEOUT_MS(既定)と BASH_MAX_TIMEOUT_MS(上限)を指定できます。名前と扱いは版で変わることがあるので、手元の版のドキュメントで確認してから使ってください。
{"env": {"BASH_DEFAULT_TIMEOUT_MS": "300000", "BASH_MAX_TIMEOUT_MS": "1200000"}} 対処2: 10分を超えるならバックグラウンドで起動し、ログで待つ
上限の10分でも足りない処理は、ツール呼び出しの中で完走させようとしないのがコツです。起動と待機を別の呼び出しに分けます。
起動側はログをファイルに落とし、終了コードもファイルに書かせます。
setsid nohup sh -c 'blender --background --python render.py > render.log 2>&1; echo $? > render.rc' \
> /dev/null 2>&1 < /dev/null &
echo started 待機側は短い呼び出しを繰り返し、終了コードのファイルが現れたかだけを見ます。
test -f render.rc && echo "rc=$(cat render.rc)" || tail -n 3 render.log Bash ツールには run_in_background オプションもあり、これを使えば起動側の setsid nohup を書かずに済みます。どちらの方式でも、待機側の1回の呼び出しは数秒で返るので、2分の壁に当たりません。
対処3: 処理そのものを分割する
レンダリングやバッチ変換のように分割できる処理なら、1回の呼び出しを2分以内に収める方が単純です。
# フレームを100枚ずつ分ける例(各回が既定の2分に収まる粒度にする)
blender --background --python render.py -- --start 1 --end 100
blender --background --python render.py -- --start 101 --end 200 分割すると途中経過が見えるので、失敗したときのやり直し範囲も狭くなります。
見分け方: cron の 143 と混同しない
| 手がかり | Bash ツールのタイムアウト | cron / systemd の SIGTERM |
|---|---|---|
| 終了コード | 143 | 143 |
| 付随する一文 | Command timed out after Nm Ns が出る | 出ない |
| 発生タイミング | 既定なら実行開始からきっかり2分 | ジョブの上限や再起動のタイミングで不定 |
| 対処 | ツール側 timeout か分割 | ジョブ側の設定を見る |
「Command timed out after」の一文があるかどうかで、ほぼ即断できます。
まとめ
- Claude Code の Bash ツールは呼び出しの寿命が既定2分・上限10分で、コマンド側の
timeoutでは延びない。 - 2〜10分の処理はツール側の
timeoutパラメータ(ミリ秒)を明示する。 - 10分超は起動と待機を別の呼び出しに分け、ログファイルと終了コードファイルで待つ。
- 分割できる処理は2分以内の粒度に切るのが最も単純。
-
Exit code 143だけで判断せず、「Command timed out after」の一文の有無で cron の SIGTERM と見分ける。
よくある質問(FAQ)
timeout パラメータに 1200000(20分)を指定したらどうなりますか
上限の 600,000ms を超える値は上限に丸められます。20分かかる処理は対処2のバックグラウンド方式に切り替えてください。既定と上限を変えたい場合は、Claude Code の設定の環境変数で調整できます(手元の版のドキュメントで確認してください)。
コマンド側の timeout は無意味ですか
無意味ではありません。ツール側の寿命を長く取ったうえで、コマンド側の timeout をそれより短く設定しておくと、暴走したプロセスをコマンド側で確実に止められます。役割は「外側=呼び出しの上限、内側=処理の上限」です。
バックグラウンド実行にしたら Claude Code が結果を拾えなくなりました
バックグラウンドのプロセスは標準出力がツールに返らないので、ログと終了コードを必ずファイルに書かせてください。待機側の呼び出しでそのファイルを読めば、完了と成否を判定できます。
2分で止まったとき、途中まで書き出したファイルは残りますか
プロセスが SIGTERM で止まるまでに書き出した分は残ります。ただし途中で切れた成果物は壊れていることが多いので、再実行の前に出力先を消してからやり直すのが安全です。
