가이드

rsync 예제: 리눅스에서 파일 동기화와 백업하기

업데이트: · Skillaria.Top

rsync는 로컬과 SSH 너머의 파일을 복사하고 동기화하며, 변경된 부분만 전송합니다. 기본 명령은 rsync -avz 원본/ 사용자@호스트:/경로/입니다. -a는 권한과 시간을 보존하고, -v는 파일 목록을 보여 주며, -z는 전송을 압축합니다. --delete는 대상을 원본과 똑같이 맞추며, -n으로 먼저 결과를 시험 실행할 수 있습니다.

rsync는 리눅스에서 파일을 복사하고 동기화하는 표준 도구입니다. 같은 장비의 디스크 간, 그리고 SSH로 연결된 서버 간에 사용할 수 있습니다. cp나 scp와 가장 크게 다른 점은 바뀐 부분만 전송한다는 것입니다. 그래서 큰 디렉터리를 다시 동기화해도 몇 초면 끝납니다. 아래는 프로젝트를 서버에 올리기, 디렉터리 미러링, 제외 규칙, 스냅샷 백업, 예약 실행 같은 실전 rsync 예제입니다.

문법과 꼭 필요한 옵션

명령의 기본 형식은 다음과 같습니다.

rsync [옵션] 원본... 대상

원본과 대상은 로컬 경로이거나 사용자@호스트:/경로 형식의 원격 경로일 수 있습니다. 한쪽은 반드시 로컬이어야 합니다. rsync는 두 원격 장비 사이를 직접 복사하지 않습니다.

옵션설명
-a아카이브 모드: 재귀 복사하면서 권한, 소유자, 그룹, 수정 시간, 심볼릭 링크를 보존 (-rlptgoD와 같음)
-v전송되는 파일 목록 출력
-z네트워크 전송 시 데이터 압축
-h크기를 읽기 쉬운 단위로 표시 (K, M, G)
-P--partial --progress와 같음: 진행 상황 표시와 중단된 파일 이어받기
-n, --dry-run시험 실행: 아무것도 바꾸지 않고 무엇을 할지 보여 줌
--delete원본에 없는 파일을 대상에서 삭제
--exclude패턴에 맞는 파일 복사 안 함
-e원격 셸 지정, 예: -e "ssh -p 2222"
-H, -A, -X하드 링크, ACL, 확장 속성 보존 (-a에 포함되지 않음)

실무에서는 열 번 중 아홉 번은 로컬에서 rsync -avh, 네트워크에서 rsync -avzh면 충분합니다.

경로 끝의 슬래시: 가장 흔한 함정

초보자가 가장 많이 실수하는 부분이 원본 경로 끝의 슬래시입니다. 이 슬래시에 따라 디렉터리 자체가 복사될지, 내용물만 복사될지가 결정됩니다.

# 디렉터리 project를 /backup 안으로 복사 → /backup/project/... 가 생성됨
rsync -av project /backup/

# project의 내용물을 /backup으로 복사 → 파일이 바로 /backup/ 아래에 생김
rsync -av project/ /backup/

기억하기 쉽게 말하면, 원본 끝에 슬래시가 있으면 "이 디렉터리의 내용물"을 뜻합니다. 대상 쪽 슬래시는 의미가 없습니다. 확신이 서지 않으면 -n을 붙여 rsync가 어떤 경로를 만들려는지 확인하세요.

로컬 복사

진행 상황을 보면서 디렉터리를 외장 디스크에 복사하는 예입니다.

rsync -avhP ~/photos/ /mnt/usb/photos/

같은 명령을 다시 실행해도 처음부터 다시 복사하지 않습니다. rsync는 파일 크기와 수정 시간을 비교해서 새로 만들어졌거나 바뀐 파일만 전송합니다. 마지막 출력은 실제로 얼마나 전송되었는지 보여 줍니다.

sending incremental file list
2026/10/IMG_2041.jpg
          4.12M 100%   38.40MB/s    0:00:00 (xfr#1, to-chk=0/1534)

sent 4.13M bytes  received 9.25K bytes  2.76M bytes/sec
total size is 6.82G  speedup is 1,648.21

speedup 값은 전체를 복사하는 것에 비해 전송량이 몇 배 적은지를 보여 줍니다.

SSH를 통한 rsync: 서버로 올리고 내려받기

원격 경로에서는 rsync가 기본적으로 SSH를 사용하므로 따로 설정할 것이 없습니다. 일반적인 ssh 로그인이 되면 됩니다. 키를 쓰면 비밀번호를 묻지 않아서 cron에도 등록할 수 있어 편리합니다.

# 사이트를 서버에 업로드
rsync -avz ./site/ deploy@203.0.113.10:/var/www/site/

# 서버의 로그를 내 컴퓨터로 내려받기
rsync -avz deploy@203.0.113.10:/var/log/nginx/ ./nginx-logs/

# 비표준 SSH 포트와 특정 키 사용
rsync -avz -e "ssh -p 2222 -i ~/.ssh/deploy_key" ./site/ deploy@203.0.113.10:/var/www/site/

rsync는 양쪽 장비에 모두 설치되어 있어야 합니다. 원격에서 SSH로 rsync를 실행하기 때문입니다. 원격에 없으면 rsync: command not found가 나옵니다. 이때는 패키지를 설치하세요(sudo apt install rsync 또는 sudo dnf install rsync).

~/.ssh/config에 별칭으로 등록된 호스트도 rsync가 이해합니다. 예: rsync -avz ./site/ prod:/var/www/site/.

서버에서 root 권한이 필요할 때

대상 파일의 소유자가 root이고 일반 사용자로 접속한다면, 원격 rsync를 sudo로 실행할 수 있습니다.

rsync -avz --rsync-path="sudo rsync" ./conf/ admin@server:/etc/myapp/

이 방법을 쓰려면 서버의 sudoers에서 rsync를 비밀번호 없이 실행할 수 있어야 합니다. 그렇지 않으면 명령이 입력을 기다리며 멈춥니다.

디렉터리 미러링: --delete

기본적으로 rsync는 파일을 추가하고 갱신하기만 하고 아무것도 지우지 않습니다. 대상을 원본과 완전히 같게 만들려면 --delete가 필요합니다.

rsync -avh --delete ~/projects/ /mnt/backup/projects/

매우 강력하지만 위험한 옵션입니다. 경로를 잘못 쓰면(예: 빈 원본이나 빠진 슬래시) 대상의 데이터가 지워질 수 있습니다. 그래서 규칙은 하나입니다. --delete가 들어간 명령은 반드시 먼저 -n으로 실행하세요.

$ rsync -avhn --delete ~/projects/ /mnt/backup/projects/
sending incremental file list
deleting old-app/README.md
deleting old-app/
app/main.py

sent 1.20K bytes  received 64 bytes  2.53K bytes/sec
total size is 18.4M  speedup is 14,554.39 (DRY RUN)

deleting 줄은 지워질 항목을 보여 줍니다. 모두 맞다고 확인되면 -n 없이 실행하세요.

유용한 변형도 있습니다. --delete-after는 전송이 끝난 뒤에 삭제하므로 대상이 더 오래 완전한 상태로 남습니다. --backup --backup-dir=/mnt/backup/deleted-$(date +%F)는 삭제하거나 덮어쓰는 파일을 지우지 않고 별도 디렉터리로 옮깁니다.

제외 규칙: --exclude와 --include

배포나 백업에서 임시 파일, 의존성, 비밀 정보를 제외하는 것은 흔한 일입니다.

# 여러 패턴 지정
rsync -avz --exclude='.git/' --exclude='node_modules/' --exclude='*.log' ./app/ server:/srv/app/

# 파일에 적힌 패턴 사용
rsync -avz --exclude-from='.rsyncignore' ./app/ server:/srv/app/

.rsyncignore은 한 줄에 패턴 하나씩 적는 단순한 목록입니다.

.git/
node_modules/
*.log
.env
tmp/

패턴 동작 방식은 다음과 같습니다.

  • 맨 앞에 슬래시가 없는 패턴(*.log)은 모든 깊이에서 일치합니다.
  • 맨 앞에 슬래시가 있는 패턴(/tmp/)은 전송의 루트에만 적용되어, 최상위 tmp만 제외합니다.
  • 끝에 슬래시가 있는 패턴(cache/)은 "디렉터리만"을 뜻합니다.
  • 규칙은 위에서부터 순서대로 검사하며, 처음 일치하는 규칙이 적용됩니다.

마지막 항목에서 "필요한 것만 복사하기" 기법이 나옵니다. 먼저 허용하고, 나머지를 금지하는 방식입니다.

# 구조를 유지하면서 .conf 파일만 복사
rsync -av --include='*/' --include='*.conf' --exclude='*' /etc/ ./etc-confs/

여기서 --include='*/'는 rsync가 모든 하위 디렉터리로 들어갈 수 있도록 필요합니다. 빈 디렉터리를 만들지 않으려면 --prune-empty-dirs(-m)를 추가하세요.

rsync로 백업하기

단순한 일일 복사본

홈 디렉터리를 두 번째 디스크에 백업하는 최소한의 방법입니다.

rsync -aH --delete --exclude='.cache/' /home/alice/ /mnt/backup/alice/

이 방식의 단점은 버전이 하나뿐이라는 것입니다. 파일을 잘못 고쳤는데 백업이 그 상태로 동기화되어 버리면 이전 버전은 사라집니다.

--link-dest로 증분 스냅샷 만들기

--link-dest 옵션은 이 문제를 거의 공짜로 해결합니다. 바뀌지 않은 파일은 복사하지 않고, 이전 스냅샷의 파일을 가리키는 하드 링크로 만듭니다. 각 스냅샷은 완전한 복사본처럼 보이지만, 실제로 차지하는 공간은 변경된 부분뿐입니다.

#!/bin/bash
set -euo pipefail

SRC="/home/alice/"
DEST="/mnt/backup/snapshots"
TODAY="$(date +%F)"

mkdir -p "$DEST"
rsync -aH --delete \
  --exclude='.cache/' \
  --link-dest="$DEST/latest" \
  "$SRC" "$DEST/$TODAY"

ln -sfn "$DEST/$TODAY" "$DEST/latest"

처음 실행할 때는 latest 디렉터리가 아직 없으므로 rsync가 경고를 출력하고 전체 복사를 합니다. 이것은 정상입니다. 오래된 스냅샷은 평범하게 rm -rf로 지우면 됩니다. 다른 스냅샷이 참조하는 파일은 사라지지 않습니다.

30일이 지난 스냅샷을 지우려면 다음과 같이 합니다.

find /mnt/backup/snapshots -maxdepth 1 -type d -name '20*' -mtime +30 -exec rm -rf {} +

서버를 다른 장비로 백업하기

백업 장비가 데이터를 직접 가져오는 방향("백업 서버 → 작업 서버")으로 설정하는 것이 좋습니다. 그러면 작업 서버에는 백업에 대한 접근 권한이 없습니다. 작업 서버가 해킹당해도 백업은 안전하게 남습니다.

rsync -azH --delete -e "ssh -i /root/.ssh/backup_key" \
  backup@web01:/var/www/ /srv/backups/web01/www/

데이터베이스는 이 방식으로 복사하면 안 됩니다. 실행 중인 DBMS의 파일은 복사하는 순간 일관성이 없습니다. 먼저 덤프(mysqldump, pg_dump)를 만들고, rsync가 완성된 덤프 파일을 옮기도록 하세요.

cron으로 예약 실행하기

백업 스크립트는 crontab -e로 cron에 등록합니다.

# 매일 03:15에 실행, 출력은 로그에 기록
15 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

cron에서 백업이 실제로 동작하도록 확인할 사항은 다음과 같습니다.

  • cron의 PATH는 최소한이고 현재 디렉터리도 다르므로, 스크립트에는 절대 경로를 쓰세요.
  • SSH 키에 비밀번호가 없어야 하고, 호스트가 이미 known_hosts에 있어야 합니다. 그렇지 않으면 rsync가 호스트 신뢰 여부를 묻는 상태에서 멈춥니다.
  • 스크립트에서 종료 코드를 확인하세요. rsync는 성공하면 0, 일부 파일을 전송하지 못하면 23, 복사 중에 파일이 사라지면 24를 반환합니다.
  • 두 복사본이 동시에 실행되는 것은 flock으로 막을 수 있습니다: flock -n /tmp/backup.lock /usr/local/bin/backup.sh.

cron 대신 systemd 타이머를 쓸 수도 있습니다. 타이머는 출력을 journal에 기록하므로 journalctl로 결과를 확인하기 편합니다.

대용량 전송에 유용한 옵션

작업옵션
회선을 가득 채우지 않도록 속도 제한--bwlimit=5M
연결이 끊긴 큰 파일 이어받기-P (또는 --partial)
파일 목록 대신 전체 진행률 표시--info=progress2
수정 시간이 아니라 내용으로 비교-c (--checksum), 더 느림
대상에 더 새로운 파일이 있으면 건드리지 않기-u (--update)
기존 파일을 덮어쓰지 않기--ignore-existing
전송 후 원본 파일 삭제 (이동)--remove-source-files
끝에 자세한 통계 출력--stats

자주 하는 실수와 해결법

  • 쓰기 중 Permission denied — 대상 디렉터리에 대한 권한이 없습니다. 디렉터리 소유자를 확인하거나 --rsync-path="sudo rsync"를 사용하세요.
  • 파일이 매번 처음부터 다시 복사됨 — 수정 시간이 보존되지 않습니다. -a 또는 -t가 있는지 확인하세요. FAT/exFAT에서는 시간이 2초 단위로 저장되므로 --modify-window=2를 추가하세요.
  • USB 메모리나 네트워크 폴더로 복사할 때 chown 또는 chgrp 오류 — 파일 시스템이 소유자를 지원하지 않습니다. -a를 -rlt로 바꾸세요.
  • 불필요한 중첩 /backup/project/project — 원본 끝의 슬래시를 잘못 썼습니다.
  • connection unexpectedly closed — SSH 문제이거나 원격에 rsync가 설치되지 않았습니다. 일반 ssh 로그인과 서버의 rsync 설치를 확인하세요.

정리

일상 작업에는 몇 가지 명령만 기억하면 됩니다. SSH 복사는 rsync -avz 원본/ 호스트:/대상/, 미러링은 --delete와 시험용 -n을 함께, 불필요한 파일은 --exclude, 스냅샷 백업은 --link-dest를 쓰세요. 원본 끝의 슬래시만 조심하면 rsync는 장비 사이에서 파일을 옮기는 가장 믿을 만한 방법이 됩니다. 동기화와 백업은 리눅스 과정에서 실습으로 다룹니다.

자주 묻는 질문

rsync가 scp보다 나은 점은 무엇인가요?

scp는 매번 파일 전체를 복사하지만, rsync는 바뀐 부분만 전송하고, 이어받기, 대상의 불필요한 파일 삭제, 패턴 기반 제외를 지원합니다. 파일 하나를 한 번 복사하는 경우에는 차이가 거의 없지만, 정기적인 동기화에서는 rsync가 훨씬 빠릅니다.

Windows에서도 rsync를 쓸 수 있나요?

네, WSL에서 리눅스와 같은 방식으로 설치해 쓸 수 있고, Cygwin을 통해서도 가능합니다. Windows 컴퓨터와 리눅스 서버를 동기화하려면 WSL에서 실행하는 것이 가장 편리합니다.

rsync는 전송 데이터를 암호화하나요?

rsync 자체는 암호화하지 않지만, SSH로 복사하면 모든 트래픽이 암호화된 SSH 연결로 전달됩니다. 암호화 없이 전송되는 경우는 rsync:// 주소로 rsync 데몬에 접속할 때뿐입니다.

복사본이 원본과 같은지 어떻게 확인하나요?

rsync -avnc 원본/ 대상/을 실행하세요. -c 옵션은 파일을 체크섬으로 비교하고, -n은 아무것도 바꾸지 않습니다. 목록이 비어 있다면 두 복사본은 동일합니다.

rsync를 전송 도중에 중단하면 어떻게 되나요?

이미 전송이 끝난 파일은 그대로 남고, 완료되지 않은 파일은 기본적으로 삭제됩니다. 같은 명령을 다시 실행하면 중단된 지점부터 이어서 진행되며, -P 옵션을 쓰면 중단된 파일의 일부도 보존됩니다.

영상으로 이 주제 배우기

이 주제는 “Linux: с нуля до уверенного администрирования” 강의에서 실습과 함께 자세히 다룹니다.

강의로 이동