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
두 개의 디렉토리 와 가 있다고 가정합니다 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