1. Summary(概要)
Claude Code を使って機械学習モデルを学習、評価する実験を回していたら、いつの間にかハードディスク使用率が 95% になっていました。調べてみると /tmp ディレクトリに 78GB あり、その全部が Claude Code の作業ディレクトリでした。
とりあえず先に結論だけ書きます。
- 溜まっていた場所は
/tmp/claude-<UID>/ - これは Claude Code がセッションごとに作る一時作業領域(scratchpad)
- 自動削除はされますが 30 日後 であり、ディスクが逼迫していると間に合わない
- 「削除して良いかどうか」の調査は、 Claude にやってもらった
- 消していいかどうかは日付だけで判断してはいけない らしい。バックグラウンドジョブが動いている場合があるとのこと
- 判定は 3 段階で実施してくれた
- 削除したら 49GB 空いた
2. 症状: いつの間にかディスク使用率が 95%
機械学習の学習ジョブを回そうとしたところ、ディスクが足りないと Claude に注意された。
$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv 489G 444G 26G 95% /
489GB のうち、空き容量は 26GB のみ...カタカタ((((꒪꒫꒪ ))))カタカタ
その後、心当たりのある学習データやモデルの重みを消しましたが、思ったほど減らない。
そこでルートから順に確認したところ、/tmp の容量が異様に大きいことに気がつきました。
$ sudo du --max-depth 1 -h /
173G ./home
167G ./var
77.8G ./tmp ← ここ
5.2G ./usr
...
413G .
/home はデータセットやモデルパラメータ、/var は Docker image が格納されているので想定通りでした。しかし /tmp に 77.8GB は明らかにおかしい。/tmp は一時ファイルの置き場のはず。ということで対処することにしました。
3. 原因
原因は、 Claude による一時作業フォルダ — 通称 scratchpad — でした。
3-1. 状況確認
中を見てみると、 /tmp/claude-<UID>/ で大量の容量を食っていた。
$ du -h -d1 /tmp | sort -hr | head -5
77.8G /tmp
76.5G /tmp/claude-1000 ← ほぼ全部これ
372M /tmp/python-build.20260827142749.147677
369M /tmp/python-build.20260827142233.134722
156M /tmp/ds014v2
claude-1000 の 1000 は自分の UID です。id -u で確認できます。
$ id -u
1000
さらに深掘りすると...
$ du -h -d1 /tmp/claude-1000/-home-ubuntu | sort -hr | head -6
76.5G /tmp/claude-1000/-home-ubuntu
58.0G /tmp/claude-1000/-home-ubuntu/691dd251-6a57-4a59-94ba-b8979a713cf2
16.8G /tmp/claude-1000/-home-ubuntu/7f82bd79-b15e-4fd4-9e81-3b400a490679
794M /tmp/claude-1000/-home-ubuntu/ec88fccd-79df-4676-86da-319ac0d384c0
413M /tmp/claude-1000/-home-ubuntu/0336a72e-420e-4535-9d3f-f434e7cf307f
278M /tmp/claude-1000/-home-ubuntu/d4931e6b-c9c5-4c50-8e97-faa2743af88d
たった 2 つのセッションで 75GB を占めていました。
これらは、 Claude が作業中に用意する一時作業用領域です。中には scratchpad などとも呼ばれているものがあり、私の場合はこれが元凶でした。
3-2. /tmp/claude-/ の中身 : scratchpad とは何か
ディレクトリ構造はこうなっています。
/tmp/claude-<UID>/<プロジェクトパス>/<セッションID>/
├── scratchpad/ ← Claude が作業ファイルを置く場所
└── tasks/ ← バックグラウンド実行したコマンドの出力ログ
Claude Code は「プロジェクトに置きたくない中間ファイル」をこの scratchpad に置きます。試しに書いたスクリプト、調査結果の一時ファイル、ちょっとした検証用のデータなどです。プロジェクトを汚さないための良い仕組みなのですが、セッションが終わっても片付きません。
私の場合は、ここに以下のようなものが入ってました。
セッション A(58GB) — 「VLA の学習で LoRA とフルファインチューニングのどちらが良いか」を検証した回
| 中身 | サイズ | 正体 |
|---|---|---|
venv |
8.5G | 検証用に作った Python 仮想環境 |
init/ |
10.9G | 変換した初期重み |
data_quantile/ |
27.8G | 学習データ |
out/.../checkpoints/000010 |
15.0G | 10 ステップだけ回した動作確認のチェックポイント |
最後の 15GB が象徴的です。「設定が正しいか確認するために 10 ステップだけ回してみる」という、完全に使い捨て前提の産物が 15GB ありました。
セッション B(16.8GB) — データセットの動作確認をした回。空回し(dry run)のときに置いたデータセットのコピーが 17GB。
セッション A / B ともに、本番の成果物は別の場所に保存済みで、scratchpad に残っていたのは検証の残骸だけでした。
3-3. なぜ消えないのか — 自動削除は 30 日後
「/tmp なんだから再起動すれば消えるのでは?」と思うところですが、サーバーは再起動しません。
Ubuntu では systemd-tmpfiles が /tmp を掃除します。
自動削除設定が気になる方は以下を開いて見てください。
自動削除設定の確認方法
設定を確認してみます。
$ cat /usr/lib/tmpfiles.d/tmp.conf | grep -v '^#' | grep -v '^$'
D /tmp 1777 root root 30d
$ systemctl is-active systemd-tmpfiles-clean.timer
active
読み方はこうです。
-
D— 再起動時に/tmpの中身を空にする -
30d— タイマーによる定期掃除では、30 日経過したものを削除する
つまり「放置しても 30 日後には消える」のですが、逆に言えば 30 日は残り続けます。ディスクが 95% の状況では待っていられません。
なお、この値はディストリビューションや設定によって違います。自分の環境で上記のコマンドを叩いて確認してください。
4. 対処方法
以下は、この困った /tmp を削除して良いかわからない方向けの情報です。 (ほとんど Claude に調べさせましたが、、、)
4-1. 消していいかどうかの見分け方
私たちの知らないところで Claude が生成したファイルたち。どのデータを消して良いのかわからないですよね?なので、ここから先の調査は Claude に任せました。
が、やり方が気になる方は以下に Claude による調査手順を記載しているので、中身を見てみても良いと思います。
削除して良いかを判断する方法を確認する
Claude は以下のようにして、 /tmp 以下のファイル群を削除して良いか調査してくれました。
日付が古いから消す、は危険です。 理由は後述しますが、scratchpad からバックグラウンドジョブが動いていることが実際にあります。学習やビルドを setsid nohup で切り離して走らせていると、何日も動き続けます。
私 (Claude) は次の 3 段階で判定しました。
4-1-1. 再開待ちのセッションが使っていないか
Claude Code のプロセスは、会話を再開(resume)していると引数にセッション ID を持ちます。
$ ps -eo pid,etime,args | grep '[c]laude' | grep -o 'resume=[0-9a-f-]*'
resume=1aee43b7-b2cd-43c7-a873-b08c33f6acf6
resume=ec88fccd-79df-4676-86da-319ac0d384c0
resume=9aa16892-2af2-4a47-b854-63bf5eed60df
grep のパターンを '[c]laude' と書いているのは、grep 自身がヒットするのを避けるためです。
ここに出てきた ID の scratchpad は触りません。私が消そうとしていた 2 つはここに含まれていませんでした。
4-1-2. 会話記録の最終更新を見る
Claude Code の会話履歴は次の場所に保存されています。
~/.claude/projects/<プロジェクトパス>/<セッションID>.jsonl
ディレクトリ名と会話記録のファイル名が同じセッション ID なので、1 対 1 で対応します。
$ ls -l --time-style=long-iso ~/.claude/projects/-home-ubuntu/691dd251-*.jsonl
-rw------- 1 ubuntu ubuntu 5049534 2026-09-17 08:37 .../691dd251-....jsonl
4 日前でした。もう一方は 6 日前。
これは参考情報です。この段階では、まだ消してはいけません。
4-1-3. そのディレクトリを掴んでいるプロセスが無いか
これが決定的な確認です。
Linux では /proc/<PID>/ 以下から、各プロセスの状態が読めます。
-
/proc/<PID>/cwd— カレントディレクトリ -
/proc/<PID>/fd/*— 開いているファイル -
/proc/<PID>/cmdline— 起動時のコマンドライン
自分が起動したプロセスであれば sudo なしで読めます。Claude Code もそこから起動されたジョブも自分のプロセスなので、これで十分です。
次のスクリプトを用意しました。
#!/bin/bash
# 使い方: bash check_scratchpad.sh <セッションID>
SID="$1"
[ -z "$SID" ] && { echo "usage: $0 <session-id>"; exit 1; }
hit=0
for pid in $(ls /proc 2>/dev/null | grep -E '^[0-9]+$'); do
[ "$pid" = "$$" ] && continue
cmd=$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)
# 検査スクリプト自身が引数に ID を持つので除外する(自己一致)
case "$cmd" in *check_scratchpad.sh*) continue ;; esac
case "$cmd" in *"$SID"*) echo "[cmdline] pid=$pid ${cmd:0:100}"; hit=1 ;; esac
case "$(readlink "/proc/$pid/cwd" 2>/dev/null)" in
*"$SID"*) echo "[cwd] pid=$pid"; hit=1 ;;
esac
for fd in "/proc/$pid/fd/"*; do
case "$(readlink "$fd" 2>/dev/null)" in
*"$SID"*) echo "[open fd] pid=$pid $(readlink "$fd")"; hit=1 ;;
esac
done
done
if [ "$hit" = 0 ]; then
echo "=> 参照しているプロセスはありません(削除して安全)"
else
echo "=> 使用中です(削除しないでください)"
fi
実行するとこうなります。
$ bash check_scratchpad.sh 691dd251-6a57-4a59-94ba-b8979a713cf2
=> 参照しているプロセスはありません(削除して安全)
4-1-4. ハマりどころ 1: 必ず「陽性対照」を取る
ここで一度立ち止まってください。
「何も出ませんでした」という結果は、検査が壊れていても得られます。 パスの書き間違い、権限不足、スクリプトのバグ。どれでも静かに 0 件になります。
そこで、動いていることが分かっているセッション ID でも同じ検査を回します。
$ bash check_scratchpad.sh ec88fccd-79df-4676-86da-319ac0d384c0
[cmdline] pid=3478576 /home/ubuntu/.vscode-server/extensions/anthropic.claude-code.../claude
[open fd] pid=3478576 /tmp/claude-1000/-home-ubuntu/ec88fccd-.../tasks
=> 使用中です(削除しないでください)
ちゃんと検出されました。これで「0 件」が信用できる 0 件になります。
実験でいう陽性対照です。地味ですが、消えたら戻らないものを扱うときは必ずやったほうがいいです。
4-1-5. ハマりどころ 2: 検査スクリプト自身に一致する
最初に書いたスクリプトでは、こんな結果が出ました。
[cmdline] pid=3560401 bash -c TARGETS="691dd251-6a57-4a59-94ba-b8979a713cf2 ..."
検査スクリプト自身のコマンドラインにセッション ID が入っているので、自分にヒットしています。
これは pkill -f や pgrep -f でも同じ現象が起きる、Linux では古典的な罠です。pkill -f myjob が自分自身を巻き込んで死ぬ、というやつですね。
上のスクリプトでは case "$cmd" in *check_scratchpad.sh*) continue ;; で除外しています。
4-1-6. 実際に使用中のセッションの scratchpad もあった
余談ですが、検査中に見つかったものを紹介します。
pid=3543347 bash /tmp/claude-1000/-home-ubuntu/ec88fccd-.../scratchpad/run_build2.sh
別のセッションが scratchpad からビルドスクリプトを実行中でした。
日付だけ見て一括削除していたら、これを壊していたところです。手順 3 が必要な理由が、まさにこれです。
4-2. 削除する
消しても良いと判断できたフォルダは消しましょう。
お馴染みの、 rm -r で消せば良いです。こんな風に。
$ rm -rf /tmp/claude-1000/-home-ubuntu/691dd251-6a57-4a59-94ba-b8979a713cf2
$ rm -rf /tmp/claude-1000/-home-ubuntu/7f82bd79-b15e-4fd4-9e81-3b400a490679
5. 削除結果
5-1. ディスク容量の解放状況
削除結果は以下のとおりです。
$ du -sh /tmp
3.1G /tmp ← 77.8G から
これにより、 49GB 空きました。 du の合計は 75GB でしたが、ハードリンク共有分があったので実際の解放はこの数字です。
共有相手だったデータセット側も確認しましたが、ファイル数もハッシュも変わらず無傷でした。リンク数が 2 から 1 に減っただけです。
5-2. du の数字は当てにならない
「合計 75GB だから 75GB 空くだろう」と思っていたら、そうはいきませんでした。
セッション A の 58GB のうち、27.8GB は別の場所とハードリンクで実体を共有していました。以前の Claude セッションが、プロジェクト側のデータセットに対してコピーではなくハードリンクを張っていたためです。
ハードリンクは「同じ実体に複数の名前が付いている」状態なので、片方を消してもディスクは 1 バイトも空きません。
5-3. 消えるもの・消えないもの
安心材料として書いておきます。
scratchpad を消しても、会話履歴は消えません。
会話記録は ~/.claude/projects/ 以下に別で保存されているので、後からそのセッションを読み返すことも、再開することもできます。
失われるのは、 Claude とのセッション中に作られた中間ファイルだけです。私の場合は動作確認用のモデルパラメータ、再構築できる仮想環境、再ダウンロードできるデータセットでした。
(これは Claude 向けの注意事項ですが...) 逆に言うと、「ここにしか無いもの」を scratchpad に置いてはいけません。残したい成果物は、プロジェクト配下なり別のストレージなりに移しておきましょう。
6. 予防: そもそも溜めないために
同じことを繰り返さないための対策です。
1. 大きな中間ファイルを作ったら、その場で消してもらう
Claude に作業を頼むとき、「検証が終わったら中間ファイルを消してください」と一言添えるだけで変わります。実際、私の会話履歴には Claude 自身が
rm -rf out/lora_fix_verify && echo "検証チェックポイントを消した"
を実行した記録が残っていました。意識はしてくれているので、明示的に頼めば効きます。
2. 定期的に見る
見逃してしまうことはどうしてもありますので、大容量ファイルが放置されることを防ぐために、時々確認しても良いと思います。
# 純粋に Claude が溜め込んでいるファイル全部を見る
du -h -d1 /tmp/claude-$(id -u)/
# 以下のように打つと、ディスク使用量が大きい順に並べてくれる
du -h -d1 /tmp/claude-$(id -u)/*/ 2>/dev/null | sort -hr | head
7. 終わりに
「/tmp が膨らんでいる」だけなら、たいていの人は中身を見ずに rm -rf してしまうと思います。実際それで済むことがほとんどです。
ただ今回は、別のセッションが scratchpad からビルドを走らせている最中でした。一括で消していたら、何時間か分の作業を失っていたはずです。
消えたら戻らないものを扱うときは、
- 使っている人(プロセス)がいないか、実際に確かめる
- その確認方法が機能していることを、陽性対照で確かめる
- 消したときに本当に空くのか、事前に測る
この 3 つをやっておくと安心です。少し手間ですが、du と find と /proc を見るだけなので、慣れれば数分で終わります。
どなたかの参考になれば幸いです。