storage / knowledge

rsync를 두 번 돌려 옮긴 데이터 검증하기

paul 2025.10.09 396words (2m)

수 TB를 한 번 복사하고 "끝났습니다" 메시지를 믿을 수는 없다. 옮긴 뒤에 원본을 지울 거라면 더 그렇다. 1차 복사 → 검증 → 2차 보정 순으로 돌렸다.

빼야 할 것

Synology에서 넘어오는 데이터에는 옮길 필요 없는 것들이 섞여 있다.

text
@eaDir
.DS_Store
#recycle
#snapshot

exclude.txt 로 저장해두고 쓴다. @eaDir 은 Synology가 썸네일과 인덱스를 넣어두는 폴더라 양이 꽤 된다. #recycle 은 휴지통이다.

1차 복사

먼저 --dry-run 을 붙여 무엇이 옮겨질지 본다.

console
$ rsync --dry-run -e "ssh -i ~/.ssh/id_ed25519" -rltDvP \
    --info=progress2 --stats --exclude-from=exclude.txt \
    ${XPE_USER}@${XPE_HOST}:/volume1/data/ /mnt/Backup/ingest/data/

확인했으면 --dry-run 을 빼고 실행한다.

옵션
-e ssh 연결 방식 지정
-r recursive
-l symbolic link를 링크 그대로
-t timestamp 유지
-D 장치 파일
-v verbose
-P partial + progress. 끊겨도 이어받는다
--info=progress2 파일 단위가 아니라 전체 진행률

-a 를 쓰지 않고 필요한 것만 골랐다. -a 에는 소유자와 그룹 보존이 들어 있는데, Synology와 TrueNAS의 UID/GID가 다르므로 그대로 옮겨봐야 의미가 없다.

검증

여기가 핵심이다. --checksum 을 붙이고 --dry-run 으로 돌린다.

console
$ rsync --dry-run -e "ssh -i ~/.ssh/id_ed25519" -rltvO --checksum \
    --info=stats2 --itemize-changes --exclude-from=exclude.txt \
    --log-file=~/data.log \
    ${XPE_USER}@${XPE_HOST}:/volume1/data/ /mnt/Backup/ingest/data/

--checksum 은 크기와 시각이 아니라 파일 내용의 해시를 비교한다. 느리지만 실제로 내용이 같은지 보는 유일한 방법이다. --dry-run 이라 아무것도 바꾸지 않고 차이만 알려준다.

--itemize-changes 로 무엇이 다른지 한 줄씩 찍고, --log-file 로 남긴다. 양이 많아 화면으로는 못 본다.

-O(--omit-dir-times)를 붙였다. 디렉토리의 mtime을 맞추려다 나는 잡오류를 막는다.

2차 보정

차이가 있으면 다시 채운다.

console
$ rsync -e "ssh -i ~/.ssh/id_ed25519" -rltvO --append-verify --delete \
    --info=stats2,progress2 --exclude-from=exclude.txt \
    --log-file=~/data_fix.log \
    ${XPE_USER}@${XPE_HOST}:/volume1/data/ /mnt/Backup/ingest/data/

--append-verify 는 중간에 끊겨서 잘린 파일을 이어받되, 이어받기 전에 이미 받은 부분의 checksum을 확인한다. 그냥 --append 는 이 확인을 하지 않아서 앞부분이 깨져 있으면 깨진 채로 완성된다.

--delete 는 원본에 없는 것을 받는 쪽에서 지운다. 1차 때 잘못 들어간 게 있으면 여기서 정리된다.

code 23을 어떻게 읽을지

rsync가 exit code 23으로 끝나는 일이 잦다. "일부 파일이 전송되지 않았다"는 뜻인데, 실제로는 파일 내용이 아니라 속성 문제인 경우가 대부분이다.

console
$ grep -E "rsync:|failed|denied|No such|error" /tmp/rsync.err | uniq -c

로그가 전부 이런 형태면 데이터는 다 갔다.

text
failed to set times on ... Operation not permitted

mtime이나 ACL, 소유권을 목적지에 못 쓴 것이다. 위에서 -O 를 붙인 것도 이 때문이다.

반대로 이런 게 섞여 있으면 그 파일만 다시 봐야 한다.

text
Permission denied
No such file or directory

전송량이 원본과 맞는데 code 23이 나왔다면 앞쪽일 가능성이 높다. 그래도 --checksum 검증은 돌려야 확인이 된다.