Linux 1個のディレクトリに大量ファイルの処理
 2012.10.05

一つのディレクトリに大量のファイル(10万以上)を作成してしまい「コピーもできない、ファイルの確認もできないで困っている」というエマージェンシーコールを受けた事が何度かあります。サーバ運用におけるありがちなトラブルの一つです。

あるお客さんのサーバではWebアプリケーションで作成されるcacheファイルが45万個ありました。また、別のお客さんのサーバではMaildirのメールスプールにエラーメールが190万個ありました…。

そんな時の対処法を紹介します。

ファイルの確認

最近のLinuxディストリビューションであればフォーマット時に dir_index オプションが有効になっているはず。なので実は大量ファイルを作成する事自体は極端なパフォーマンス悪化にはなりません。

パフォーマンスの問題を実感するのは、大量ファイルを持つディレクトリで安易に ls を実行したとき。これは ls がファイルの一覧を取得し sort を行うから。なのでソートを行わないオプション(-U)を使えばそんなに遅くないのです、本当は。

[sourcecode lang="bash" light="1"]
$ /bin/ls -U manyfiles/
00235610
00303636
00121968
00164484
00147265
00205845
00335831
00179442
00351647
00146621
[/sourcecode]

/bin/ls と絶対パスで起動しているのは"ls"に設定されている alias を無効にするためです。
以下のように色付けされて表示されるようオプションが無意識に設定されている可能性があります。

[sourcecode lang="bash" light="1"]
$ which ls
alias ls='ls --color=auto'
/bin/ls
[/sourcecode]

ls -U の実行結果ではファイル名の一覧だけが取得できます。ファイルのパスが欲しい場合は find コマンドを使います。ls -U より若干遅いですが。

[bash light="1"]
$ find manyfiles
manyfiles
manyfiles/00684423
manyfiles/00235610
manyfiles/00303636
manyfiles/00121968
manyfiles/00164484
manyfiles/00147265
manyfiles/00828936
manyfiles/00205845
manyfiles/00335831
[/bash]

これでファイルの中身を確認するなど何とか可能なはずです。

ファイルの削除

大量のファイルができてしまうという事はそのディレクトリに関しては今までほったらかしだったはずです。なので、現実的な対策は丸ごと削除する という事になります。削除にもそれなりに時間がかかるので、パーミッションが同一のディレクトリを予め作成しておき、入れ替える処理を行います。

[bash light="1"]
$ echo manyfiles |cpio -pdm new
$ mv manyfiles manyfiles.REMOVE ; mv new/manyfiles .
[/bash]

これで空の manyfiles と、大量ファイルが存在する manyfiles.REMOVE ができます。manyfiles.REMOVE は普通に rm -fr などで削除します。

manyfiles 以下にサブディレクトリやシンボリックリンク等、保存しておきたい場合は以下のようにコピーしておきます。

[bash light="1"]
$ find manyfiles -type d | cpio -pdm new
$ find manyfiles -type l | cpio -pdm new
[/bash]

manyfiles 以下で最近アクセスしたファイルは残したいなどの要求も find と cpio でコピーしておきます。

[bash light="1"]
$ find manyfiles -atime -7 |cpio -pdm new
[/bash]

最終アクセス時刻が7日以内の場合はコピー対象になります。

ゆっくり削除

サーバに負荷をかけずに削除したい場合は以下のコマンドでできます。

[bash light="1"]
$ cat filelist | perl -lne 'unlink; sleep(2) if $.%200==0'
[/bash]

200個のファイルを削除するたびに2秒間sleepを行います。負荷の程度や処理時間に応じて調整してください。sleepする時間を大きくする、sleepを入れるタイミング(削除するファイル数)を少なくするとよりサーバへの影響が少なくなります。ディレクトリの削除は行いませんので、ファイル削除後に手動で対処します。

まとめ

  • ファイルの一覧を取得するのは遅くない。
  • 対処法はばっさり削除が現実的。
  • 一つのディレクトリに大量ファイルを作成しない設計方針を採用する。
  • /usr/sbin/tmpwatch などで定期的に削除する運用を採用する。
カテゴリー:技術情報メモ