古いファイルを一括削除する perl script
サーバの Disk 容量が足りなくなってきたので、Amazon Search とかの Web Service として提供しているアプリケーションのコンテンツ・キャッシュファイルを、ある一定期間更新がされていないファイルを一括削除することにしました。
簡単な削除スクリプトを書いてみました。キャッシュをファイルベースで管理している場合に、ひょっとして他の方にも役立つかも?と思ってソースを公開しておこうかなぁーと思って。
#!/usr/local/bin/perl use strict;
use File::Find;
use 5.6.0;
use constant CACHE_DIR => '/temp-path'; ## 削除したいディレクトリのpath
use constant EXPIRE => 50; ## 削除対象とする経過日数 find(\&filter, CACHE_DIR); sub filter {
eval {
my $hash = {
Mrange => int(-M $_),
Arange => int(-A $_),
Crange => int(-C $_),
dir => $File::Find::dir,
name => $File::Find::name,
};
if( $hash->{Mrange} < EXPIRE ) {
print "[ok] $hash->{Mrange} $hash->{dir} $hash->{name}\n";
} else {
my $name = $File::Find::name;
qx{ rm -rf "$name" };
print "[rm] $hash->{Mrange} $hash->{dir} $hash->{name}\n";
}
};if($@) { print $@; }
}
ちなみに、先週から週末を開発の時間に割り当てて、Amazon Search と Google Similar のコンテンツ管理を MySQL ベースに変更しようと思いプログラム変更をしていたのですが、全然パフォーマンスがでなくてお蔵入りしてしまいました。
今のファイルベースのキャッシュの仕組みは、コンテンツの内容(属性)を情報として LDAP のような構造をとるようにディレクトリを階層化して管理しているので、index とかが無くても1パスで目的のファイルに辿り着く仕組みになっていて、非常に高速に read/write できるように作っています。
一方、MySQL にした場合は適切なインデックス経由でデータにアクセスするようになるのですが、MySQL も非常に高速なので問題はでないだろうと予測していたのですが、数百万レコード単位になると、さすがに現状のように1パスでアクセスできるような仕組みと比較して遅いという結果になってしまいました。
現状の仕組みだと、集計作業やちょっとしたメンテナンスを全体的に行う場合に、全ファイルを総なめする必要があってメンテナンス性に難があるので、DB 化したいなぁ〜と思っていたのですが、当分は現状のまま運用するしかなさそうです・・・。
コメントやシェアをお願いします!
drk
通りすがりさん>なるほど!これは一本やられました。find に -mtime オプションがあるって知りませんでした。
これからソレ使います!
通りすがり
わざわざスクリプト組まなくても
find /tmp-path -type f -mtime +50 | xargs rm
ではダメなの?
詳細は man find にて
drk
PhotoXP さん>書き忘れましたが、Amazon Search の場合、7日後にキャッシュを破棄して再作成するんですよ。なので更新日時をみてます。ご指摘の通り、通常の場合は、ctime を見るのが良いですよね。
上のスクリプトで言うと、Crange で比較するよう変更すればOKな感じで。
PhotoXP
いつもお世話になってます。
古いファイルの削除は、findコマンドと-mtime -ctimeで消すのがいいのでは?(^_^