オプション1

オプション1

次のような構造があるとしましょう。

$ mkdir d1
$ mkdir d1/d2
$ touch d1/f1
$ touch d1/d2/f2

$ chmod u-w d1/d2

削除しようとするとd1書き込み権限がないため削除できませんd1/d2。しかし、まだ削除されますd1/f1

$ rm -rf d1
rm: cannot remove 'd1/d2/f2': Permission denied

$ ls d1
d2          # f1 has been deleted

原子ツールを実装する方法はありますかrm?たとえば、すべてのアイテムを削除できない場合、何も削除されません。

ベストアンサー1

私はツリーのハードリンクバックアップを作成する方法でこのプログラムを作成します。その後、操作が失敗した場合は、削除されたファイルをバックアップから復元します。ジョブが成功すると、ハードリンクバックアップは削除されます。

もちろん、これは「いつでも電源コードを抜くことができる」という意味では原子的ではなく、論理的に原子的であるだけです。もちろん、追加のロジックと起動時に実行されるいくつかのフックを使用してソートすることもできます。

2回のパス(1つは権限確認用、もう1つは削除用)を作成するのは難しいです。拡張属性を含むすべての権限を確認するには、ロジックを徹底する必要があります。たとえば、これを行うと、通常のUnix権限が大丈夫に見えても、書き込みsudo chattr +i file可能fileなディレクトリは削除できなくなります。 「このファイルを削除できますか?」の最高のリトマステストは、実際に試してみることです。

rsyncこれは、ハードリンクベースのバックアップとリカバリの概念証明として特定のテストを受けた概念的なプロトタイプです。スクリプト名は次のとおりですatomic-rm.sh

#!/bin/sh

set -eu

if [ $# -ne 1 ] ; then
  echo "specify directory to remove"
  exit 1
fi

ar_src=$(realpath "$1")
ar_tmp=$(mktemp -d "$(dirname "$ar_src")/tmp-XXXXXX")

if [ $? -ne 0 ] ; then
  echo "unable to create temporary directory"
  exit 1
fi

cleanup()
{
  find "$ar_tmp" -type d -print0 | xargs -0 chmod +w

  if ! rm -rf "$ar_tmp" ; then
    echo "removal of temporary directory $ar_tmp failed"
    exit 2 # 2 indicates dirty failure
  fi
}

trap cleanup EXIT

if ! rsync -ar --link-dest="$ar_src" "$ar_src"/ "$ar_tmp"/ ; then
  echo "unable to create hard-linked backup of $ar_src in $ar_tmp"
  exit 1
fi

if ! rm -rf "$ar_src" ; then
  if ! rsync -ar --link-dest="$ar_tmp" "$ar_tmp"/ "$ar_src"/ ; then
    echo "removal of $ar_src failed; unfortunately, so did the rollback"
    exit 2 # 2 indicates dirty failure
  fi
  exit 1
fi

exit 0

追加の努力をすれば、起動時にリカバリスクリプトが緩い一時ディレクトリをクリーンアップするために使用できる場所にいくつかの情報を保存できます。一時ディレクトリは削除されるディレクトリの兄弟として作成され、同じファイルシステムに存在します/tmp

削除が失敗してロールバックが実行されると、ディレクトリが混乱して修正タイムスタンプが変更されたため、ツリーの正確な状態を絶対に復元できません。

では、ディレクトリを書き込み可能にするためにディレクトリをcleanup巡回する必要があります。findこれは、ディレクトリに書き込むことができず、削除が失敗した場合、そのディレクトリrsync権限がコピーされるため、バックアップコピーでも同じように失敗するためです。

おすすめ記事