「rm -rf a/b」が「a/bが空ではない」と言うのはなぜですか?

「rm -rf a/b」が「a/bが空ではない」と言うのはなぜですか?

次のスクリプト時々私に同じことを与えるcan't remove a/b as it's not empty

ssh -T user@host <<EOF
  cd somewhere
  rm -rf a/b    
EOF

ただし、サーバーにログインして実行したrm -rf a/b後、問題は発生しませんでした。

ファイルを生成する他のプロセスがありますa/b。これは関係ありますか?

とにかく、「a / b」が削除されたことを確認するスクリプトをどのように作成できますか?

答え1

a / bにファイルを生成する他のプロセスはありますか?関係ありますか?

おそらく。おそらく、rm -rfすべてのファイルを最初に削除してから、すべてのディレクトリを削除します。その後、rmdirディレクトリが空でない場合、ディレクトリを削除するためのシステムコールは失敗します。rm -rfディレクトリが空であることを確認する競合状態がある可能性があり、その後他のプロセスが最終的にrm -rf呼び出されますが、rmdir他のプロセスはファイルを事前に生成します。

Faheemの提案は良いです。lsエラー条件を入力してください。

ssh -T user@host <<EOF
  cd somewhere
  rm -rf a/b || ( ls -a a/b && exit 1 )
EOF

答え2

rmdir(2)ディレクトリが空でない場合は失敗します。rm(1)ファイルが削除されたときに別のプロセスでファイルを作成すると、ファイルを削除する方法がわからないため、空のディレクトリと思われるコンテンツを削除しようとすると、公開したrm(1)エラーで失敗します。

ディレクトリにファイルが同時に作成されている間にディレクトリを削除する1つの方法は、名前を変更することです。

mv a a~
rm -rf a~

a/bファイルを作成したプロセスがパスを介して実行されていない場合(open(2)代わりに)openat(2)機能しない可能性があります。

ファイルが生成されるプロセスは、a/bディレクトリが存在しない場合はディレクトリを再作成し、ディレクトリが存在しない場合はエラーを正常に処理すると仮定します。すでに他のプロセスからディレクトリを削除しようとしているので、これは安全な前提のようです。

答え3

競合状態が非常に高い場合、次のコマンドは未使用のファイルを削除し、空のディレクトリを削除します。

find /somedir -type f -atime +3 -print0 | xargs -0 --no-run-if-empty rm -f; find /somedir -mindepth 1 -type d -empty -not -name "*.empty" -print0 | xargs -0 --no-run-if-empty -I{} mv {} {}.empty; sleep 30; find /somedir -type d -name '*.empty' -print0 | xargs -0 --no-run-if-empty rm -rf

または段階的に:

find /somedir -type f -atime +3 -print0 | xargs -0 --no-run-if-empty rm -f;
find /somedir -mindepth 1 -type d -empty -not -name "*.empty" -print0 | xargs -0 --no-run-if-empty -I{} mv {} {}.empty;
sleep 30;
find /somedir -type d -name '*.empty' -print0 | xargs -0 --no-run-if-empty rm -rf;

睡眠30すべてのプロセスが削除されたディレクトリへの書き込みを完了するために必要です。

警告:新しいデータが失われる可能性があります(私の場合はキャッシュなので気にしません。)

関連情報