همگامسازی و پشتیبانگیری افزایشی فایل بین سرورها با rsync
اگر چند گیگ فایل روی یک سرور دارید و هر شب باید نسخهای از آن را جایی دیگر نگه دارید، کپی کامل با scp یا tar هر بار وقت و پهنای باند زیادی میگیرد. rsync فقط تفاوت فایلها را منتقل میکند، برای همین پشتیبانگیری با rsync برای این کار دقیقا ساخته شده است.
rsync چیست و چرا برای بکاپ افزایشی مناسب است
rsync یک ابزار خط فرمان لینوکس برای کپی و همگامسازی فایلها است، هم روی یک سرور و هم بین دو سرور از راه SSH. نقطهٔ قوت آن الگوریتم delta است: قبل از انتقال، rsync بلوکهای فایل مبدا و مقصد را مقایسه میکند و فقط بخشهایی را میفرستد که تغییر کردهاند.
این یعنی اگر یک فایل لاگ 2 گیگابایتی فقط چند مگابایت آخرش عوض شده باشد، rsync کل 2 گیگ را دوباره نمیفرستد. دفعهٔ دوم که دستور را اجرا میکنید، فقط تغییرات منتقل میشوند؛ به همین دلیل به آن بکاپ افزایشی میگویند، نه اینکه هر بار یک کپی کامل جدید بسازد.
در مقایسه، scp و cp هر بار کل فایل را کپی میکنند، حتی اگر یک بایت تغییر کرده باشد. برای چند فایل کوچک فرقی نمیکند، اما برای دایرکتوری چند ده گیگابایتی بین دو سرور، همین تفاوت باعث میشود بکاپ شبانه چند دقیقه طول بکشد بهجای چند ساعت.

قبل از شروع: دسترسی SSH بدون رمز بین دو سرور
برای اینکه دستور rsync داخل cron بدون وقفه اجرا شود، سرور مبدا باید بتواند بدون وارد کردن رمز به سرور مقصد وصل شود. کلید SSH برای این کار کافی است.
# روی سرور مبدا (جایی که بکاپ از آن اجرا میشود)
ssh-keygen -t ed25519 -f ~/.ssh/rsync_backup -N ""
# کپی کلید عمومی به سرور مقصد
ssh-copy-id -i ~/.ssh/rsync_backup.pub user@backup-server
بعد از این مرحله، اتصال را یک بار تست کنید:
ssh -i ~/.ssh/rsync_backup user@backup-server "echo connected"
اگر پیام connected را بدون پرسیدن رمز دیدید، کلید درست کار میکند و میتوانید به سراغ دستور اصلی rsync بروید.
دستور پایه برای همگامسازی فایل بین دو سرور
سادهترین شکل دستور این است:
rsync -avz -e "ssh -i ~/.ssh/rsync_backup" /var/www/mysite/ user@backup-server:/backup/mysite/
فلگهایی که باید بشناسید
-aحالت archive است: زیرپوشهها، مجوزها، مالکیت فایل و زمان آخرین تغییر را حفظ میکند. بدون این فلگ، rsync فقط محتوای فایل را کپی میکند و متادیتا از بین میرود.-vخروجی را نمایش میدهد تا بفهمید دقیقا چه چیزی منتقل شده.-zداده را قبل از انتقال فشرده میکند؛ روی لینکهای اینترنتی کندتر فرق واقعی ایجاد میکند، روی شبکهٔ داخلی دیتاسنتر معمولا لازم نیست.- اسلش انتهای مسیر مبدا (
mysite/) مهم است: یعنی محتوای پوشه را بریز توی مقصد، نه اینکه خود پوشه mysite را یک پوشه جدید داخل مقصد بسازد.
اگر میخواهید مقصد دقیقا مثل مبدا بماند و فایلهایی که از مبدا حذف شدهاند هم از مقصد پاک شوند، فلگ --delete را اضافه کنید:
rsync -avz --delete -e "ssh -i ~/.ssh/rsync_backup" /var/www/mysite/ user@backup-server:/backup/mysite/
این فلگ را با احتیاط استفاده کنید. اگر مسیر مبدا را اشتباه بدهید یا یک مونتپوینت موقتا خالی باشد، --delete همان خالیبودن را روی مقصد هم اعمال میکند و بکاپ شما را پاک میکند، نه اینکه آن را بهروز کند. قبل از اجرای واقعی، یک بار با --dry-run تست بگیرید تا لیست تغییرات را بدون اجرای واقعی ببینید.
بکاپ افزایشی واقعی با اسنپشات و link-dest
دستور بالا همیشه فقط یک نسخه از مقصد را نگه میدارد. اگر فایلی امروز خراب شود و فردا همان خرابی همگامسازی شود، نسخهٔ سالم دیروز هم از بین رفته. برای داشتن چند نسخهٔ تاریخی، rsync فلگ --link-dest دارد که با hard link کار میکند.
ایدهٔ کار اینطور است: هر اجرای بکاپ یک پوشهٔ جدید با تاریخ آن روز میسازد. فایلهایی که نسبت به آخرین بکاپ تغییر نکردهاند، بهجای کپی دوباره، فقط با hard link به همان فایل قبلی اشاره میکنند. فایلهایی که تغییر کردهاند، از نو کپی میشوند. نتیجه این است که هر پوشهٔ تاریخ یک اسنپشات کامل به نظر میرسد، اما فضای دیسک فقط برای تفاوتها مصرف میشود.
DATE=$(date +%F)
rsync -avz --delete \
--link-dest=/backup/mysite/latest \
-e "ssh -i ~/.ssh/rsync_backup" \
/var/www/mysite/ \
user@backup-server:/backup/mysite/$DATE/
ssh -i ~/.ssh/rsync_backup user@backup-server \
"ln -sfn /backup/mysite/$DATE /backup/mysite/latest"
لینک نمادین latest همیشه به آخرین اسنپشات اشاره میکند و بار بعد به --link-dest معرفی میشود تا rsync بداند با کدام نسخه مقایسه کند.
مقایسه دو روش
| rsync ساده (یک نسخه) | rsync + link-dest (چند اسنپشات) | |
|---|---|---|
| فضای دیسک مصرفی | فقط اندازهٔ یک نسخه | اندازهٔ یک نسخه + فقط تفاوت هر روز |
| امکان برگشت به نسخهٔ قدیمیتر | ندارد | هر پوشهٔ تاریخ یک نسخهٔ کامل است |
ریسک --delete | فایل حذفشده برای همیشه از بکاپ هم میرود | فایل در اسنپشاتهای قبلی باقی میماند |
| پیچیدگی تنظیم | یک خط دستور | نیاز به اسکریپت کوچک برای تاریخ و لینک latest |
| مناسب برای | همگامسازی زنده بین دو سرور فعال | بکاپ شبانه که باید چند روز قابل بازیابی باشد |
برای همگامسازی زندهٔ دو سرور (مثل یک سرور اصلی و یک replica) روش ساده کافی است. برای بکاپ شبانه که ممکن است لازم باشد به نسخهٔ سه روز پیش برگردید، link-dest انتخاب درستتری است.
زمانبندی خودکار با cron
دستور بالا را در یک اسکریپت بریزید، مثلا /usr/local/bin/backup-mysite.sh، و اجراییاش کنید:
chmod +x /usr/local/bin/backup-mysite.sh
بعد با crontab -e یک خط برای اجرای شبانه اضافه کنید:
0 2 * * * /usr/local/bin/backup-mysite.sh >> /var/log/rsync-backup.log 2>&1
این خط هر شب ساعت 2 اسکریپت را اجرا میکند و خروجی را در یک فایل لاگ ذخیره میکند. بعد از چند شب، آن فایل لاگ را چک کنید؛ اگر خطی با rsync error یا Permission denied دیدید، یعنی کلید SSH یا مجوز پوشهٔ مقصد مشکل دارد، نه اینکه بکاپ درست گرفته شده باشد.
اگر با وجود این پاکسازی هم فضای دیسک تمام شد، اول همین find را چک کنید که درست اجرا شده، نه اینکه مستقیم سراغ بزرگ کردن دیسک بروید. برای پاکسازی اسنپشاتهای قدیمیتر از مثلا 14 روز، یک خط دیگر هم میتوانید به cron اضافه کنید:
30 2 * * * find /backup/mysite -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;
چند نکتهٔ عملی برای استفادهٔ واقعی
چند فایل یا پوشه را معمولا نباید همگامسازی کرد: کش، فایلهای موقت، و پوشهٔ node_modules یا vendor که دوباره قابل ساخت هستند. با --exclude این مسیرها را کنار بگذارید تا هم زمان و هم فضا صرفهجویی شود:
rsync -avz --delete --exclude 'cache/' --exclude '*.tmp' \
-e "ssh -i ~/.ssh/rsync_backup" \
/var/www/mysite/ user@backup-server:/backup/mysite/
اگر بکاپ روی یک لینک اینترنتی محدود اجرا میشود، فلگ --bwlimit=5000 سرعت انتقال را به 5 مگابایت بر ثانیه محدود میکند تا کاربران واقعی سرور در ساعت بکاپ کندی حس نکنند. و برای پوشههای خیلی بزرگ با میلیونها فایل کوچک، فلگ --progress بهجای -v خروجی خواناتری میدهد که نشان میدهد کار کجاست.
روی یک سرور مجازی که منبع و مقصد بکاپ روی آن هستند، فضای دیسک و پهنای باند شبکه همان چیزی است که سرعت این کار را تعیین میکند؛ اگر پلن فعلیتان با چند اسنپشات روزانه پر میشود، گزینهٔ اول افزایش فضای دیسک بدون قطعی است، و اگر آن هم کافی نبود، وقت بالا بردن پلن یا گرفتن یک سرور مجازی جدید برای همان بکاپ است.
سؤالات متداول
آیا rsync برای بکاپ بین دو سرور ویندوز و لینوکس هم کار میکند؟ نسخهٔ اصلی rsync برای لینوکس و مک است. روی ویندوز باید از WSL یا نسخههایی مثل cwRsync استفاده کنید؛ بین دو سرور لینوکس مستقیم و بدون نرمافزار اضافه کار میکند.
تفاوت rsync با rclone چیست؟ rsync برای سرورهایی با دسترسی SSH طراحی شده. rclone بیشتر برای فضاهای ابری مثل S3 یا Google Drive ساخته شده و از پروتکلهای متفاوتی پشتیبانی میکند؛ برای همگامسازی دو سرور لینوکس، rsync انتخاب سادهتری است.
آیا rsync میتواند جایگزین کامل یک راهکار بکاپ حرفهای شود؟ برای یک یا چند سرور با نیاز ساده، بله کافی است. برای محیطهایی با چند ده سرور یا نیاز به رمزنگاری و مانیتورینگ مرکزی، ابزارهایی مثل Borg یا Restic روی همان کلیدهای SSH مزایای بیشتری دارند.
چرا اجرای دوم rsync سریعتر از اولی است؟ چون در اجرای اول همهٔ فایلها تازه هستند و کامل منتقل میشوند. از اجرای دوم به بعد، rsync فقط فایلهای تغییریافته را پیدا و منتقل میکند، برای همین زمان اجرا معمولا چند برابر کوتاهتر میشود.
اگر همین امروز میخواهید این را تست کنید، یک سرور مقصد کوچک کافی است تا ببینید اسکریپت و cron درست کار میکنند، قبل از اینکه آن را روی سرور اصلی اجرا کنید.




