rsync chỉ gửi phần khác biệt, resume được, có dry-run: dùng cho mọi thứ lớn hơn vài file. scp cho copy nhanh một lần. Cả hai đi qua SSH nên đọc ~/.ssh/config (alias, ProxyJump): xem SSH config & jump host.
Dấu / cuối nguồn quyết định kết quả: rsync -a src/ dst/ copy nội dung src vào dst; rsync -a src dst/ tạo dst/src/. Đích không ảnh hưởng. Luôn chạy -n (dry-run) trước khi thêm --delete.
rsync cơ bản
| Mục đích | Lệnh |
|---|---|
| Copy thư mục lên server (giữ quyền, time, symlink) | rsync -avh ./site/ deploy@203.0.113.5:/var/www/site/ |
| Kéo về từ server | rsync -avh deploy@203.0.113.5:/var/log/app/ ./app-logs/ |
| Nén khi truyền (link chậm, file text) | rsync -avzh src/ host:/dst/ |
| Dry-run, liệt kê thay đổi chi tiết | rsync -avn -i src/ host:/dst/ |
| Mirror: xoá file ở đích không còn ở nguồn | rsync -av --delete src/ host:/dst/ |
| Tiến độ + giữ file dở dang để resume | rsync -avP bigfile.iso host:/data/ |
| Tiến độ tổng thay vì từng file | rsync -a --info=progress2 src/ host:/dst/ |
| Thống kê cuối | rsync -a --stats src/ host:/dst/ |
| Tạo thư mục đích còn thiếu (rsync 3.2.3+) | rsync -a --mkpath src/ host:/srv/new/path/ |
| Cần sudo ở phía remote | rsync -a --rsync-path='sudo rsync' src/ host:/etc/app/ |
Lọc file
| Mục đích | Lệnh |
|---|---|
| Bỏ thư mục và kiểu file | rsync -av --exclude '.git/' --exclude '*.log' src/ host:/dst/ |
| Danh sách exclude từ file | rsync -av --exclude-from=.rsyncignore src/ host:/dst/ |
Chỉ lấy *.cfg, giữ cấu trúc thư mục |
rsync -avm --include '*/' --include '*.cfg' --exclude '*' src/ dst/ (-m bỏ thư mục rỗng) |
| Copy theo danh sách file | rsync -av --files-from=list.txt / host:/backup/ |
| Xoá ở đích cả file đang bị exclude | rsync -av --delete --delete-excluded --exclude '*.tmp' src/ dst/ |
| Bỏ qua file lớn | rsync -av --max-size=500M src/ dst/ |
Pattern exclude tính theo đường dẫn tương đối với gốc nguồn; / đầu pattern neo vào gốc (--exclude '/cache/' chỉ bỏ cache ở cấp 1).
Hành vi so sánh và an toàn
| Mục đích | Lệnh |
|---|---|
| So bằng checksum thay vì size+mtime | rsync -avc src/ dst/ |
| Không ghi đè file đã có ở đích | rsync -av --ignore-existing src/ dst/ |
| Không ghi đè file mới hơn ở đích | rsync -avu src/ dst/ |
| Giữ bản cũ khi bị ghi đè/xoá | rsync -av --delete --backup --backup-dir=/srv/bak/$(date +%F) src/ dst/ |
| Giới hạn băng thông (KB/s) | rsync -av --bwlimit=5000 src/ host:/dst/ |
| Giữ hardlink, ACL, xattr, uid số (backup đầy đủ, chạy bằng root) | rsync -aHAX --numeric-ids /src/ /backup/ |
| Backup kiểu snapshot (hardlink file không đổi) | rsync -a --delete --link-dest=/backup/2026-11-05 /src/ /backup/2026-11-06/ |
| Di chuyển (xoá nguồn sau khi copy xong) | rsync -av --remove-source-files src/ dst/ |
SSH options, jump host
| Mục đích | Lệnh |
|---|---|
| Port SSH khác, key riêng | rsync -av -e 'ssh -p 2222 -i ~/.ssh/id_deploy' src/ host:/dst/ |
| Qua bastion | rsync -av -e 'ssh -J ops@bastion.example.com' src/ deploy@198.51.100.20:/dst/ |
Dùng alias trong ~/.ssh/config |
rsync -av src/ pe1:/tmp/src/ |
scp và sftp
| Mục đích | Lệnh |
|---|---|
| Copy file lên | scp app.tar.gz deploy@203.0.113.5:/tmp/ |
| Copy thư mục, giữ time/quyền | scp -rp ./configs deploy@203.0.113.5:/tmp/ |
Port khác (chữ P hoa) |
scp -P 2222 file host:/tmp/ |
| Qua bastion | scp -J ops@bastion.example.com file deploy@198.51.100.20:/tmp/ |
| Giới hạn băng thông (Kbit/s) | scp -l 8000 big.iso host:/data/ |
| Thiết bị/SSH server cũ chỉ hiểu giao thức SCP cũ | scp -O file admin@198.51.100.1:/ |
| Phiên sftp tương tác | sftp -J bastion deploy@198.51.100.20 (lệnh: put, get -r, ls, lcd) |
| sftp chạy batch | sftp -b cmds.txt deploy@203.0.113.5 |
Từ OpenSSH 9.0, scp mặc định dùng giao thức SFTP bên dưới; switch, router hoặc server cũ không có subsystem sftp thì thêm -O.