rsync
ソースストア(バージョン管理)のコンテンツを共有NFSマウントに同期させるプロセスがあります。
悪いことですが、他のコンテンツが別のソースからターゲットフォルダに同期されるため、ターゲットフォルダにソースフォルダよりも多くのコンテンツが含まれることがあります。たとえば、フォルダ構造は次のようになります。
源泉
a/a1.txt
a/a2.txt
b/b1.txt
目的地
a/a1.txt
a/a2.txt
a/a3.txt
b/b1.txt
c/c1.txt
(この例では、他の場所からターゲットに同期さa/a3.txt
れますc/c1.txt
。実際には、さまざまなソースが含まれており、そのソースのコンテンツ/プロセスは影響を受けません。)
ここで、ソースフォルダがファイルを削除すると仮定しますa/a2.txt
。既存の設定では、ターゲットの場所からファイルは削除されませんが、それを使用すると--delete
他のファイルが削除される可能性があるため、これを行わないように要求します。
--delete
このrsyncを使用しながら要件を満たす方法は何ですか?元のディレクトリはバージョン管理になっているため、ディレクトリの前後がわかりやすいので、元のソースディレクトリを基準に差分バックアップを計算することも可能ですが、これが最善の方法でしょうか?
答え1
この方法では使用できませんrsync --delete
。これはステートレスであり、実行中に削除されたファイルを追跡しません。この--delete
フラグは、単にソースrsync
に存在しないターゲット上のすべてのファイルを削除するように指示します。
このような制限された削除を達成するためには、自分だけの状態を維持しなければならないと思います。あなたのためにもすることもできませrsync
んunison
。
以下は、完全なエラーから安全な解決策ではありません。 (ただし、改行を含むファイルを含む奇妙な名前のファイルは処理されます。)
src
2つのディレクトリがあるとしますdst
。 (この例では、ローカルなのかリモートなのかは関係ありませんdst
。)
# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z > .state.src
バックアップを実行するたびに、次のコードを実行します。
# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/
# Determine the set of files to delete in "dst/"
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z | tee .state.src.new |
LC_ALL=C comm -z - -13 .state.src |
ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'
# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src
comm
私のバージョンと同じバージョンがGNU coreutils 8.25より前のバージョンで、対応するフラグがない場合は、次の-z
代替回避策を使用できます。
# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | tr '\0\n' '\n\0' | LC_ALL=C sort > .state.src
バックアップを実行するたびに、次のコードを実行します。
# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/
# Determine the set of files to delete in "dst/"
( cd src && find . -type f -print0 ) | tr '\0\n' '\n\0' | LC_ALL=C sort | tee .state.src.new |
LC_ALL=C comm -13 - .state.src |
tr '\0\n' '\n\0' |
ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'
# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src