
私は tmpfs /tmp に RAM を使用しています。正確には 2GB です。通常はこれで十分ですが、プロセスがそこにファイルを作成し、その後クリーンアップに失敗することがあります。これはプロセスがクラッシュした場合に発生する可能性があります。これらの孤立した tmp ファイルを削除する必要があります。そうしないと、将来のプロセスで /tmp のスペースが不足します。
/tmp を安全にガベージ コレクションするにはどうすればよいでしょうか。最終変更タイムスタンプをチェックしてこれを行う人もいますが、長時間実行されているプロセスが依然としてそれらのファイルを必要とする可能性があるため、この方法は安全ではありません。より安全な方法は、最終変更タイムスタンプの条件と、どのプロセスもファイルのファイル ハンドルを持たないという条件を組み合わせることです。この方法、または同様に安全な他の方法を具体化したプログラム/スクリプトなどはありますか。
ちなみに、Linux/Unix では、作成プロセスが終了したときに、たとえクラッシュによるものであっても、作成されたファイルが削除される、作成時にファイルを開くモードが許可されていますか?
答え1
次のようなことを試してみるといいかもしれません:
find /tmp -mtime +7 -and -not -exec fuser -s {} ';' -and -exec echo {} ';'
find は、特定の条件に一致するファイルを検索するために使用されます。
-mtime +7
7日以上経過したファイルのみを選択します(他の値を使用することもできます)-exec fuser -s {} ';'
古さの基準に一致するすべてのファイルに対して、サイレントモードでfuserを呼び出します。fuserは、現在アクセスされているすべてのファイルに対して0(=true)を返し、アクセスされていないファイルに対して1(=false)を返します。アクセスされていないファイルのみに関心があるので、-not
この前にaを付けます。-exec
-exec echo {} ';'
条件に一致するすべてのファイル名を印刷するだけです。-exec rm {} ';'
ここでは代わりに を使用することもできますが、これによりまだ使用中のファイルが削除される可能性があるため、最初に単純な echo を実行する方が安全だと思います。- 編集:偶発的な影響を避けるために、クリーンアップの影響を特定のファイル パターンまたはユーザー ID に制限するために、
-name 'foo*.bar'
またはのようなものを追加することをお勧めします。-uid 123
最後のポイント: 一度だけ書き込まれるファイル (例: システム起動時) があるが、頻繁に読み取られるファイル (例: X セッション クッキー) がある可能性があることを考慮してください。したがって、問題のあるプログラムによって作成されたファイルにのみ影響するように、名前チェックを追加することをお勧めします。
編集2: 最後の質問です。ファイルは、プロセスがオープン ハンドルを持たない限り、ディスクから削除されません (少なくともネイティブ Linux ファイルシステムの場合)。問題は、ディレクトリ エントリが即座に削除されるため、ファイルを削除した時点から新しいプロセスがファイルを開くことができなくなることです (ファイル名が添付されていないため)。
詳細については以下を参照してください。 https://stackoverflow.com/questions/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux
編集3:しかし、プロセス全体を自動化したい場合はどうすればよいでしょうか?
前述したように、一度書き込まれてから時々読み取られるファイル (X セッション クッキー、PID ファイルなど) が存在する可能性があります。これらは、この小さな削除スクリプトでは除外されません (echo
実際にファイルを削除する前に、まずテスト実行を行う必要があるのはそのためです)。
安全なソリューションを実装する方法の1つは、 を使用することですatime
。
atime
各ファイルが最後にアクセスされた時刻を保存します。しかし、このファイルシステムオプションはパフォーマンスにかなりの影響があるため、無効になっていることがよくあります(このブログ20~30% の範囲のどこかにあります。 もありますrelatime
が、 が変更された場合のアクセス時間のみを書き込むmtime
ため、これは役に立ちません。
を使用したい場合は、システム全体のパフォーマンスへの影響が大きくなりすぎないように、別のパーティション (理想的には RAM ディスク) にatime
配置することをお勧めします。/tmp
が有効になったら、上記のコマンド ラインのパラメータを にatime
置き換えるだけです。 を削除できるかもしれませんが、念のため残しておくことをお勧めします (アプリケーションがファイルを長時間開いたままにする場合に備えて)。-mtime
-atime
-not -exec fuser -s {} ';'
echo
ただし、システムにまだ必要なものを削除する前に、コマンドを使用してテストすることを忘れないでください。
答え2
自分で巻かないでください。
Debian/Ubuntu には tmpreaper があり、おそらく他のディストリビューションでも利用できるでしょう。
# tmpreaper - cleans up files in directories based on their age
sudo apt-get install tmpreaper
cat /etc/tmpreaper.conf
答え3
質問の最後の部分に関して:
「死んだら削除する」オープン/作成モードは存在しないと思いますが、プロセスは、そのファイルのハンドルを開いたままにしておけば、ファイルの作成後すぐに安全に削除できます。カーネルはファイルをディスク上に保持し、ファイルを開いた最後のプロセスが終了するとすぐに (クラッシュまたは通常の理由で)、ファイルが占めていたスペースが解放されます。
一部のプロセスが/tmpをクリーンアップしないという問題を回避する一般的な方法としては、マウント名前空間を参照することをお勧めします。たとえば、ここまたはここ問題のプロセスがシステムデーモンである場合、システムプライベートの /tmp ファイルシステムを許可するネイティブ機能も興味深いかもしれません。
答え4
特定の日付より古いファイルのリストを取得し、そのリストから何かによって開かれているファイルを除外します。
find /tmp -mtime +7 |\
egrep -v "`lsof -n +D /tmp | awk 'NR>1 {print $9}'| tr \\n \|`"
lsof -n +D /tmp
: /tmp で開いているファイルを検索します
awk 'NR>1 {print $9}'
: ヘッダーを除いた lsof 出力の 9 列目のみを出力します
tr \\n \|
: 改行を bar に置き換えます (egrep では OR)
egrep -v "foo|moo|bar"
: foo または moo または bar を含まない行を出力します