백업 도구를 사용하는 경우duplicity
,나는 알아차렸다소스에서 파일 이름을 바꾸면 데이터가 네트워크를 통해 대상으로 다시 전송됩니다., 좀 아쉽네요. 내부 duplicity
사용 으로 인해 librsync
살펴보기로 결정했습니다 rsync
.
이것건축 위키 페이지상태:
핸들 이름 바꾸기
이동되거나 이름이 변경된 파일은 감지되며 두 번 저장되거나 전송되지 않습니다. 이는 일반적으로 파일이나 해당 블록의 체크섬을 계산하는 것을 의미합니다. 이 기능이 부족한 애플리케이션은 다음과 같은 기능을 결합하여 보완할 수 있습니다.hsync
AUR , 동기 이름 바꾸기 전용입니다.
rsync: 핸들 이름 바꾸기: 아니요
이것이 정말로 의미하는 바는,사용 시 rsync
10GB가 네트워크를 통해 대상으로 재전송되는 것을 방지할 수 있는 방법이 없습니다., 소스 머신의 이름을 다음으로 바꾸면 /test/10GBfile
?/test/10GBfile_newname
의 오랜 인기를 감안할 때 rsync
이를 처리할 더 좋은 방법이 있습니까?
답변1
rsync
런타임 시를 제외하고는 상태를 유지하지 않기 때문에 이름 바꾸기를 추적하는 메커니즘이 없습니다 . 원본 머신에서 로 이름을 바꾸면 /test/10GBfile
기본적으로 삭제된 항목과 생성된 항목만 표시됩니다./test/10GBfile_newname
rsync
10GBfile
10GBfile_newname
매개변수 --fuzzy
( )는 대상에서 잠재적인 데이터 소스를 -y
식별하는 데 도움이 될 수 있으므로 파일 복사 대신 네트워크 복사를 방지할 수 있습니다. 그러나 (대부분) 파일 일치만 고려할 수 있습니다.10GBfile
10GBfile_newname
같은 디렉토리에따라서 귀하의 예는 일치하지만 이름 /test/10GBfile
을 바꾸면 /test/otherdir/10GBfile_newname
그렇지 않습니다.
또한 설명서( man rsync
)에서는 를 사용하려는 경우 또는 사용하기 전에 잠재적인 일치 항목이 제거되지 않도록 사용해야 --delete
한다고 제안합니다.--delay-updates
--delete-after
--fuzzy
예
# Prepare an uncompressible 100MB file
mkdir -p /tmp/test
dd bs=1M count=100 iflag=fullblock if=/dev/urandom >/tmp/test/file1
# Normal first-time copy
rsync -av --fuzzy --delete-after /tmp/test/ remote:/tmp/test
# Skip copy because unchanged
rsync -av --fuzzy --delete-after /tmp/test/ remote:/tmp/test
# Rename file (per your example)
mv /tmp/test/file1 /tmp/test/file2
# Fast copy because fuzzy match
rsync -av --fuzzy --delete-after /tmp/test/ remote:/tmp/test
진행 상황에 대한 블록별 세부 정보를 보려면 두 개의 -v
플래그(예: )를 더 추가하세요 .rsync -avvv …
답변2
--fuzzy
이미 답변을 받았지만 하드 링크와 관련된 또 다른 흥미로운 해킹이 있습니다.
첫 번째 전송 후
$ rsync -avHP --delete-after ~/family/Photos remotebox:backups
작업 디렉터리에 대한 하드 링크를 만듭니다.
$ cd ~/family
$ cp -rlp Photos Photos-work
그런 다음 사용할 수 있습니다
$ rsync -avHP --delete-after --no-inc-recursive ~/family/Photos ~/family/Photos-work remotebox:backups
새 구조를 리모컨으로 전송합니다.
그 이유와 작동 방식은 다음과 같습니다.
https://lincolnloop.com/blog/Detecting-file-moves-renames-rsync/
답변3
그 페이지에 옵션 패치를 --detect-renamed
사용할 수 있다고 주장합니다 rsync 3.0.9
. 여기에는 패치에 대한 링크가 있습니다.버그질라 토론. 내 것은 선택의 여지 rsync 3.1.3
가 없었습니다 --detect-renamed
. 언급된 논의는 현재 진행 중입니다:
2021-01-15 14:19:12 UTC 시간
이 기능 요청은 너무 오래되었으며 btrfs/zfs/etc가 rsync보다 더 최적화된 백업 솔루션이므로 관련성을 잃었습니다.
어떤 사람들은 "관련성 상실"에 동의하지 않으며 나는 동의하지 않는 사람들의 의견에 동의합니다.
저것레딧 페이지주장하다:
btrfs sync는 이 기능을 지원하지만 양쪽 끝에 btrfs가 필요합니다.
내가 생각하는 것에이라트라트말하는.
다음은 내 현재 솔루션입니다( git
제 생각에는 약간 과잉이라고 생각합니다).
내 구체적인 상황: 나는 이름을 자주 바꾸지 않으며 백업이 아닌 동기화된 링크(일대일이 아닌)를 원합니다. 그래서 mv
rsync를 앞뒤로 실행하기 위해 원래 작성한 스크립트에 의해 추가로 실행될 명령(마지막에 새 명령 추가)을 작성하는 쉘 명령 파일을 만들기로 결정했습니다 . 이 스크립트는 많은 테스트를 거치지 않았으므로 위험을 감수하고 실행해야 하며 개선을 위한 제안을 환영합니다. rsync --detect-renamed
옵션이 곧 출시되기를 바랍니다 .
다음 전체 스크립트는 동기화 한쪽의 셸 파일 크기가 다른 쪽의 셸 파일보다 클 때 이를 별도로 처리하고 확실하지 않기 때문에 몇 가지 검사를 포함하기 때문에 꽤 깁니다(최근에 시작했기 때문에). 이 스크립트를 사용하여) comm
프로그램 여부 올바르게 발견된 유일한 줄은 아마도 "정렬된"(맨 페이지별) 파일에 적용된다는 것입니다. 핵심은 다음과 같습니다.
# do renames / moves at both ends
cd $remote_path
bash -c "$(comm --nocheck-order -3 -1 $f_RE $f_LO)"
cd $local_path
bash -c "$(comm --nocheck-order -3 -2 $f_RE $f_LO)"
# merge files via temp file
(comm --nocheck-order -1 -2 $f_LO $f_RE) > $f_LO.3
(comm --nocheck-order -3 -1 $f_RE $f_LO) >> $f_LO.3
(comm --nocheck-order -3 -2 $f_RE $f_LO) >> $f_LO.3
cp $f_LO.3 $f_RE
mv $f_LO.3 --force $f_LO
rm $f_LO.1 $f_LO.2
전체 쉘 기능:
#!/bin/bash
do_sync(){
if [ -d $remote_path ]; then
# ===== workaround for renaming / moving (run manually made commands before rsync) ===== #
# man comm: comm - compare two sorted files line by line
complex_flag=0 # later set by script to 1 if changes identified from both sync directions
to_rsync=1 # to run rsync by default
f_RE=$remote_path/_rename_move.sh
f_LO=$local_path/_rename_move.sh
if [ -f $f_RE ]; then
if [ -f $f_LO ]; then
# if both exist, -gt greated than, stat --printf="%s" size in bytes
if [ $(stat --printf="%s" $f_RE) -gt $(stat --printf="%s" $f_LO) ]; then
# small file (2nd) is fully contained in the beginning of larger file (maybe test binary mode more efficient)
# -1 suppress column 1 (lines unique to FILE1) : man comm
if [ -z "$(comm --nocheck-order -3 -1 $f_RE $f_LO)" ]; then
# run only additional commands
cd $local_path
bash -c "$(comm --nocheck-order -3 -2 $f_RE $f_LO)"
# overwrite small with larger one
cp $f_RE $f_LO
else complex_flag=1; fi
# remote smaller than local
elif [ $(stat --printf="%s" $f_RE) -lt $(stat --printf="%s" $f_LO) ]; then
# small file (1nd) is fully contained in the beginning of larger file (maybe test binary mode more efficient)
if [ -z "$(comm --nocheck-order -3 -2 $f_RE $f_LO)" ]; then
# run only additional commands
cd $remote_path
bash -c "$(comm --nocheck-order -3 -1 $f_RE $f_LO)"
# overwrite small with larger one
cp $f_LO $f_RE
else complex_flag=1; fi
# same size but different contents
elif [ ! $(sha256sum $f_RE | awk '{ print $1 }') = $(sha256sum $f_LO | awk '{ print $1 }') ]; then
complex_flag=1;
fi
# nothing to do if files are the same
# if only remote exists
else
cd $local_path && $f_RE
fi
# neither file was found to be part of another as a whole
# expect changes (moves/renames) from both ends
if [ $complex_flag -eq 1 ]; then
# doing echo "$()" removes trailing empty lines compared to for some reason (TODO why?)
# check that doing symmetrically with appending to local results in same number of lines in a file
# and selecting matching in both and adding distinct from both too results in same number of lines in a file
cp $f_RE $f_LO.1 && (comm --nocheck-order -3 -1 $f_RE $f_LO) >> $f_LO.1
cp $f_LO $f_LO.2 && (comm --nocheck-order -3 -2 $f_RE $f_LO) >> $f_LO.2
(comm --nocheck-order -1 -2 $f_LO $f_RE) > $f_LO.3
(comm --nocheck-order -3 -1 $f_RE $f_LO) >> $f_LO.3
(comm --nocheck-order -3 -2 $f_RE $f_LO) >> $f_LO.3
counts_1="$(wc $f_LO.1 | awk '{ print $1,$2,$3 }')"
counts_2="$(wc $f_LO.2 | awk '{ print $1,$2,$3 }')"
counts_3="$(wc $f_LO.3 | awk '{ print $1,$2,$3 }')"
# same counts, Ok
if [ $counts_1 = $counts_2 ] && [ $counts_2 = $counts_3 ]; then
cd $remote_path
bash -c "$(comm --nocheck-order -3 -1 $f_RE $f_LO)"
cd $local_path
bash -c "$(comm --nocheck-order -3 -2 $f_RE $f_LO)"
cp $f_LO.3 $f_RE
mv $f_LO.3 --force $f_LO
rm $f_LO.1 $f_LO.2
else
echo "========= manual intervention might be needed ==========="
echo "Results of analysis of $f_LO & $f_RE via [comm] app has not matched;"
echo "renaming/moving not performed;"
echo "rsync of $local_path & $remote_path not performed; see differences between files:"
echo "$f_LO.1, $f_LO.2, $f_LO.3"
echo "========================================================="
to_rsync=0
fi
fi
# if only local exists
elif [ -f $f_LO ]; then
cd $remote_path && $f_LO
fi
# ===== end of workaround ===== #
if [ $to_rsync -eq 1 ];then
rsync $options $local_path/ $remote_path
rsync $options $remote_path/ $local_path
rsync $options $local_path/ $remote_path
fi
# below is to move old versions away
find "$local_path" -path "$local_path/prevs" -prune -o -name '*.bak' -exec mv "{}" "$local_path/prevs" \;
find "$remote_path" -path "$remote_path/prevs" -prune -o -name '*.bak' -exec mv "{}" "$remote_path/prevs" \;
# previous versions, prune works "more correct", forgot why
# find $local_path -maxdepth 1 -name '*.bak' -exec mv "{}" $local_path/prevs \;
# find $remote_path -maxdepth 1 -name '*.bak' -exec mv "{}" $remote_path/prevs \;
else
echo $remote_path is not available
fi
}
# trailing / would prevent proper pruning in find commands
local_path=/home/$(id -un)/Documents
remote_path=/media/$(id -un)/Projects
do_sync
정답은https://serverfault.com/questions/489289/handling-renamed-files-or-directories-in-rsync내가 이해한 바로는 몇 가지 단점이 있습니다.
하드 링크 사용: 대부분의 시스템은 디렉토리에 대한 하드 링크를 지원하지 않으며 어느 쪽의 이름이 변경되었는지 확인하지 않습니다(백업은 가능하지만 동기화는 불가능함).
stat filename
파일의 어느 쪽 이름이 바뀌었는지 확인하는 데 사용할 수 있지만 rsync와 병합하는 방법을 모르겠습니다.