公開日:

目標使用量ベースのファイル削除ツールを公開

Authors
  • author image
    Name
    代表取締役 宮永邦彦
    Twitter
    @miyanaga
  • 画像軽量化とWebフロントエンドのスピード改善の専門家です。Web系のIT技術大好き。

    このサイトではスピード改善のリアルや、日々の技術的な気づきを共有します。

システムにおいて、キャッシュファイルやバックアップファイルはできるだけ長く保持しておきたいが、それによりストレージの空き容量が枯渇することは避けたい。

findコマンドを使い、例えば「1 週間以上古いファイルを削除する」といったスクリプトの例はよく目にする。しかし本質的な解決にはなっていない。1 週間でどのくらいストレージを消費するかは正確には予測できないからだ。

そこで以下の Go 言語製ツールを公開した。

このツールを使えば「10GB に収まるよう古いファイルから削除する」といった目標使用量に応じたクリーニングを実行できる。


使い方

詳しくは README を参照いただきたいが、以下のように目標容量と対象ディレクトリを指定して実行するだけだ。

bash
file-cleaner 10gb /var/cache

この例では/var/cacheディレクトリ内の使用量が 10GB に収まるように古い順にファイルを削除する。

特徴

最終更新時刻と最終アクセス時刻に対応

バックアップファイルは最終更新時刻が新しいものに価値が大きいが、キャッシュファイルの場合は最終アクセス時刻が新しいファイルの方が高価値であることが一般的だ。

そこで-aオプションを指定すると最終アクセス時刻を基準に古いファイルを判定する。

ブロックサイズベースの計算

このツールでは論理的なファイルサイズではなく、ディスク上で占有するブロックサイズを基準にして使用量を計算する。

目的はディスクの空き容量の枯渇を防止することなので、論理ファイルサイズでは誤差が生じる。特に小さなファイルが大量にある場合はその誤差が顕著になる。

UNIX 系 OS であればブロックサイズを自動的に検知する。それ以外の OS では一般的なブロックサイズである4kb=4096を用いるが、--block-sizeオプションで指定することもできる。

省メモリの工夫

この手の実装例では、すべてのファイルの時刻をメモリに保持してソートすることが多い。しかし大量にファイルがある場合、その処理はメモリを圧迫する。

このツールではファイルの時刻を 1 時間単位に切り上げて集計する。正確性には欠けるがメモリの使用量は最大 3600 分の 1 に抑えられる。

切り上げの単位は-bオプションで指定できる。例えば-b 600sと指定すると切り上げ単位は 10 分になるので、時間的に密度の高いキャッシュファイルも効率よく削除できる。

並列処理による高速化

-cオプションで並列度を指定し、処理の高速化を図ることができる。

そもそもディレクトリスキャンを並列化すると本当に時間の短縮ができるのかは、以下のベンチマークで検証した。

もちろん並列化が常によいとは限らない。ディレクトリ数が少ないケースや、ディスク I/O のボトルネックが大きい場合はそこまで効果を見込めないばかりか、ミューテックスやチャネルによる同期処理のオーバヘッドで返って非効率になることもある。

--dry-runオプションでリハーサルもできるので、実際に高速化できるか使用するまえに確認いただくとよいだろう。

まとめ

このように、大量のファイルがある場合にもディスクをできるだけ有効活用しながら古いファイルを効率よく削除する、という処理には工夫したい点がいろいろとあった。

シェルスクリプトだけではそこまで追求できず、かといって毎回プログラムを実装するのは面倒だ。それが本ツールを開発した動機である。

うっかりサーバーのストレージ使用量が 100%になっていた、という事態を避けるためにも、ぜひ活用いただきたい。

おまけ

このツールは最後に再帰的に空ディレクトリの削除も行う。

空ディレクトリの削除もよくある例なので、別のプロジェクトに分けてみた。