web-dev-qa-db-ja.com

サーバーに影響を与えずに何百万ものファイルを削除する方法

Nginxキャッシュディレクトリを削除したいと思います。

mv cache cache.bak
mkdir cache
service nginx restart

今、私はcache.bakフォルダには200万のファイルがあります。サーバーに影響を与えずに削除します。

シンプルな rm -rf cache.bakはサーバーを破壊します。最も単純なHTTP応答でさえ、rmの実行中に16秒かかるため、実行できません。

私は試した ionice -c3 rm -rf cache.bak、しかしそれは助けにはならなかった。サーバーにSSDではなくHDDがあります。SSD上に問題がない可能性があります。

最善の解決策は、nginxの組み込みキャッシュマネージャーのように、ある種のスロットリングになると思います。

これをどのように解決しますか?これを正確に行うことができるツールはありますか?

ubuntu 16.04上のext4

11
hyperknot

私はここで多くの有用な答え/コメントを得ました、そして私は私の解決策を示すだけでなく、結論もしたいと思います。

  1. はい、防止するための最善の方法は、キャッシュディレクトリを別のファイルシステムに保持することです。ファイルシステムのNuking /クイックフォーマットは、ファイルに存在するファイル/ディレクトリの数に関係なく、常に最大で数秒(おそらく数分)かかります。

  2. ionice/Niceソリューションは何もしませんでした。削除プロセスでは実際にはほとんどI/Oが発生しなかったためです。 I/Oの原因は、削除プロセスによってファイルがあまりに速く削除されたときにカーネル/ファイルシステムレベルのキュー/バッファがいっぱいになると私が信じていたためです。

  3. 私がそれを解決した方法は、Tero Kilkanenのソリューションに似ていますが、シェルスクリプトを呼び出す必要はありませんでした。削除の速度を制限するために、rsyncの組み込み--bwlimitスイッチを使用しました。

完全なコマンドは:

mkdir empty_dir
rsync -v -a --delete --bwlimit=1 empty_dir/ cache.bak/

現在、bwlimitは帯域幅をキロバイト単位で指定しています。この場合、帯域幅はファイル名またはファイルのパスに適用されます。これを1 KBpsに設定すると、1時間あたり約100,000ファイル、つまり1秒あたり27ファイルが削除されていました。ファイルにはcache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1eのような相対パスがあり、47文字の長さであるため、1秒あたり1000/47〜= 21ファイルになるため、私の推測では1時間あたり100,000ファイルと似ています。

なぜ--bwlimit=1なのか私はさまざまな値を試しました:

  • 10000、1000、100->システムは以前と同様にスローダウン
  • 10->システムはしばらくの間は非常にうまく機能していますが、1分に1回程度、部分的に速度が低下します。 HTTP応答時間はまだ1秒未満です。
  • 1->システムのスローダウンはまったくありません。私は急いでいないので、200万のファイルがこの方法で1日未満で削除される可能性があるので、それを選択します。

私はrsyncの組み込みメソッドの単純さが好きですが、この解決策は相対パスの長さに依存します。ほとんどの人は試行錯誤によって正しい値を見つけるため、大きな問題ではありません。

2
hyperknot

次のようなbashスクリプトを作成します。

#!/bin/bash
rm -- "$*"
sleep 0.5

たとえば、deleter.shという名前で保存します。 chmod u+x deleter.shを実行して実行可能にします。

このスクリプトは、引数として渡されたすべてのファイルを削除し、0.5秒スリープします。

その後、実行できます

find cache.bak -print0 | xargs -0 -n 5 deleter.sh

このコマンドは、cache.bak内のすべてのファイルのリストを取得し、一度に5つのファイル名を削除スクリプトに渡します。

したがって、一度に削除されるファイルの数、および各削除操作間の遅延時間を調整できます。

9
Tero Kilkanen

誰かがコメントで述べたようにマウント/アンマウントできる別のファイルシステムにキャッシュを保存することを検討する必要があります。あなたがするまで、あなたはこれを1つのライナー/usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -delete検索バイナリが/ usr/binの下にあり、進行状況を画面に表示したいとします。 HDDに過度のストレスをかけないように、それに応じてスリープを調整してください。

4
Alex

Findコマンドの出力を消費するスクリプトでioniceを試してみるとよいでしょう。次のようなもの:

ionice -c3 $(
for file in find cache.bak -type f; do
    rm $file
done
for dir in find cache.bak -depthe -type d -empty; do
    rmdir $dir
done
)

ファイルシステムによっては、各ファイルを削除すると、ディレクトリ全体が書き換えられる可能性があります。かなりヒットする可能性のある大きなディレクトリの場合。 iノードテーブルに必要な追加の更新があり、場合によっては空き領域リストがあります。

ファイルシステムにジャーナルがある場合、変更はジャーナルに書き込まれます。適用された;ジャーナルから削除されました。これにより、書き込み集中型アクティビティのI/O要件が増加します。

キャッシュ用のジャーナルのないファイルシステムを使用したい場合があります。

Ioniceの代わりに、sleepコマンドを使用してアクションをレート制限できます。これはioniceが機能しない場合でも機能しますが、すべてのファイルを削除するには長い時間がかかります。

3
BillThor