انتقال اطلاعات با rsync

rsync ابزار استاندارد لینوکس برای انتقال و همگام‌سازی فایل بین دو مسیر یا دو سرور است و مزیت اصلی آن این است که به‌جای کپی دوباره همه‌چیز، فقط تفاوت‌ها را منتقل می‌کند. اگر هنوز مطمئن نیستید کدام ابزار به کارتان می‌آید، مقایسه scp، sftp و wget برای انتقال فایل روی SSH نشان می‌دهد هرکدام برای چه نوع انتقالی ساخته شده‌اند. فرمان پایه برای انتقال اطلاعات از یک سرور لینوکسی به سرور دیگر روی SSH این است، اما پیش از اجرای واقعی حتماً یک‌بار آن را با --dry-run تست بگیرید:

rsync -avz --progress -e 'ssh -p 2222' /var/www/html/ root@SERVER_IP:/var/www/html/

در ادامه سوئیچ‌های ضروری، معنای اسلش انتهایی مسیر مبدأ و خطرناک‌ترین گزینه یعنی --delete را بررسی می‌کنیم.

rsync دقیقاً چه فرقی با کپی معمولی دارد؟

در روش‌هایی مثل scp یا انتقال یک آرشیو tar، هر بار کل حجم داده دوباره روی شبکه می‌رود. rsync از الگوریتم delta استفاده می‌کند: فایل مبدأ و مقصد را به بلوک‌های کوچک می‌شکند، برای هر بلوک checksum می‌گیرد و فقط بلوک‌هایی را می‌فرستد که در مقصد وجود ندارند یا تغییر کرده‌اند.

نتیجه عملی این است که اجرای اول ممکن است زمان‌بر باشد، ولی اجرای دوم و سوم روی همان مسیر بسیار سریع تمام می‌شود. به همین دلیل rsync هم برای مهاجرت (migration) مناسب است و هم برای بکاپ‌های تکرارشونده. فقط توجه کنید انتقال فایل همه کار مهاجرت نیست؛ برای نمونه تفاوت کاراکترست دو سرور می‌تواند بعد از انتقال به خطای MySQL Error 1118 منجر شود. اگر در حال جابه‌جایی سایت یا دیتابیس به یک سرور مجازی ابری جدید هستید، معمولاً یک همگام‌سازی سنگین اولیه می‌گیرید، سرویس را در بازه کم‌ترافیک متوقف می‌کنید و یک اجرای کوتاه دوم فقط تغییرات باقی‌مانده را می‌برد.

rsync باید روی هر دو طرف نصب باشد؛ با rsync --version بررسی و در صورت نبود با apt install rsync یا dnf install rsync نصبش کنید. همین ابزار پیش از نصب مجدد سیستم عامل (Rebuild) کردن سرور مجازی هم لازم می‌شود، چون ریبیلد کل دیسک را پاک می‌کند و باید داده‌ها را از قبل بیرون برده باشید.

سوئیچ‌هایی که واقعاً لازم دارید

-a حالت archive؛ معادل -rlptgoD است و زیرپوشه‌ها، لینک‌های نمادین، سطح دسترسی، زمان تغییر و مالکیت را حفظ می‌کند.
-v نمایش نام فایل‌های در حال انتقال.
-z فشرده‌سازی داده در مسیر شبکه.
-P معادل --partial --progress؛ درصد پیشرفت را نشان می‌دهد و فایل ناتمام را برای ادامه بعدی نگه می‌دارد.
-h نمایش حجم‌ها با واحد خوانا.
-n همان --dry-run؛ شبیه‌سازی بدون نوشتن چیزی.
--numeric-ids انتقال UID و GID به‌صورت عددی؛ وقتی نام کاربران دو سرور یکسان نیست از تغییر ناخواسته مالکیت جلوگیری می‌کند.
--bwlimit=5000 محدود کردن پهنای باند مصرفی برحسب کیلوبایت بر ثانیه.

درباره -z یک نکته عملی وجود دارد: اگر داده‌ها از قبل فشرده‌اند (آرشیو، ویدئو، تصویر) فشرده‌سازی دوباره فقط CPU مصرف می‌کند و سودی ندارد. روی لینک سریع بین دو سرور فیزیکی در یک دیتاسنتر، حذف -z اغلب انتقال را سریع‌تر می‌کند؛ روی اتصال کند یا بین‌المللی نگه‌داشتن آن منطقی است.

اجرای rsync روی SSH با پورت غیراستاندارد

در این شکل از اجرا، rsync پورت جداگانه‌ای باز نمی‌کند و داده روی همان کانال SSH جابه‌جا می‌شود (حالت daemon که سرویس و پورت مستقل خودش را دارد، بحث جداگانه‌ای است). روش عوض کردن خود پورت SSH هم در تغییر پورت سرور آمده است. اگر پورت SSH سرور مقصد پیش‌فرض نیست، آن را با -e یا شکل بلندش --rsh اعلام کنید:

rsync -avzh -e 'ssh -p 2222' /home/user/data/ root@SERVER_IP:/backup/data/

rsync -avzh --rsh='ssh -p 2222' /home/user/data/ root@SERVER_IP:/backup/data/

مقدار بعد از -p پورت SSH مقصد و مقدار بعد از @ آی‌پی یا هاست‌نیم مقصد است. برای انتقال در جهت معکوس، یعنی کشیدن اطلاعات از سرور راه دور به سرور فعلی، کافی است ترتیب دو آرگومان را جابه‌جا کنید:

rsync -avzh -e 'ssh -p 2222' root@SERVER_IP:/var/www/html/ /var/www/html/

پیش از انتقال حجیم، ورود بدون رمز با کلید را تنظیم کنید (ssh-keygen و ssh-copy-id -p 2222 root@SERVER_IP) تا اگر ارتباط قطع شد و مجبور به اجرای دوباره شدید، پشت پرامپت رمز گیر نکنید.

اول dry-run، بعد انتقال واقعی

پرهزینه‌ترین اشتباهات rsync از یک مسیر اشتباه تایپ‌شده می‌آید. همیشه ابتدا دستور را با -n اجرا کنید تا فهرست کارها چاپ شود، بدون آنکه چیزی نوشته یا حذف گردد:

rsync -avhn --delete -e 'ssh -p 2222' /var/www/html/ root@SERVER_IP:/var/www/html/

افزودن -i یا --itemize-changes خروجی را دقیق‌تر می‌کند و نشان می‌دهد هر فایل به چه دلیل منتقل می‌شود. وقتی خروجی همان چیزی بود که انتظار داشتید، همان دستور را بدون -n اجرا کنید.

اسلش انتهایی مبدأ؛ کلاسیک‌ترین خطای rsync

این تنها نکته‌ای است که بیشترین ساختار پوشه خراب‌شده را در مهاجرت‌ها ایجاد می‌کند. اسلش انتهای مسیر مبدأ معنا دارد، اسلش مقصد تقریباً بی‌اثر است:

  • rsync -a /var/www/html/ /backup/html/ یعنی «محتوای داخل html را بریز داخل مقصد» و نتیجه /backup/html/index.php می‌شود.
  • rsync -a /var/www/html /backup/html/ یعنی «خود پوشه html را بریز داخل مقصد» و نتیجه /backup/html/html/index.php می‌شود.

یک اسلش جاافتاده باعث می‌شود فایل‌ها یک لایه عمیق‌تر بنشینند و در انتقال یک سایت پرحجم یا محتوای یک هاست دانلود ممکن است تازه بعد از چند ساعت متوجه شوید. عادت کنید مبدأ را همیشه با اسلش بنویسید و نتیجه را با -n تأیید کنید.

کنار گذاشتن کش و فایل‌های بی‌مصرف

پوشه‌های کش، لاگ و ماژول‌های قابل بازسازی معمولاً بخش بزرگی از حجم را می‌سازند و ارزش انتقال ندارند. با --exclude آن‌ها را حذف کنید (هر الگو یک سوئیچ جدا):

rsync -avzhP --exclude='wp-content/cache/' --exclude='*.log' --exclude='node_modules/' -e 'ssh -p 2222' /var/www/html/ root@SERVER_IP:/var/www/html/

اگر فهرست الگوها بلند شد، آن‌ها را در یک فایل متنی خط‌به‌خط بنویسید و با --exclude-from=/root/exclude.txt بدهید. الگویی که با اسلش شروع شود (مثل /tmp/) فقط به ریشه مسیر مبدأ اشاره می‌کند، در حالی که tmp/ هر پوشه tmp را در هر عمقی کنار می‌گذارد.

هشدار؛ سوئیچ --delete حذف می‌کند

گزینه --delete مقصد را دقیقاً آینه مبدأ می‌کند؛ یعنی هر فایلی که در مقصد هست و در مبدأ نیست پاک می‌شود. این رفتار برای بکاپ‌های آینه‌ای مفید و در عین حال مخرب است. سه قاعده را رعایت کنید:

  • هرگز --delete را بدون اجرای قبلی با -n اجرا نکنید.
  • مسیر مبدأ و مقصد را دو بار بخوانید؛ ترکیب --delete با اسلش اشتباه می‌تواند محتوای یک پوشه پر را با پوشه‌ای خالی جایگزین کند.
  • اگر مبدأ به هر دلیل خالی یا mount نشده باشد، rsync آن را «حذف همه‌چیز» تعبیر می‌کند. برای مقاومت در برابر این حالت از --delete-after همراه با --max-delete=100 استفاده کنید تا اگر تعداد حذف‌ها غیرمنتظره بالا رفت، عملیات متوقف شود.

انتقال طولانی را داخل screen اجرا کنید

اگر ارتباط SSH شما وسط انتقال قطع شود، فرایند هم کشته می‌شود. دستور را داخل screen یا tmux اجرا کنید تا مستقل از نشست شما ادامه پیدا کند:

screen -S migrate سپس دستور rsync را اجرا کنید و با Ctrl+A و بعد d از آن جدا شوید؛ برای بازگشت screen -r migrate.

حتی اگر انتقال نیمه‌کاره ماند، اجرای دوباره همان دستور به‌لطف الگوریتم delta و --partial از جایی که مانده ادامه می‌دهد و کار تکراری انجام نمی‌شود.

بعد از انتقال چه چیزی را بررسی کنیم؟

یک اجرای پایانی با -n بگیرید؛ اگر خروجی تقریباً خالی بود، دو طرف همگام هستند. سپس مالکیت و سطح دسترسی فایل‌ها را در مقصد کنترل کنید، چون کاربر وب‌سرور در دو سرور ممکن است متفاوت باشد و همین موضوع باعث خطای دسترسی سایت می‌شود. دیتابیس هم با rsync منتقل نمی‌شود؛ برای آن خروجی mysqldump بگیرید و فایل خروجی را جداگانه بفرستید. اگر ترجیح می‌دهید مهاجرت و پیکربندی بعد از آن را به تیم فنی بسپارید، خدمات مدیریت سرور همین کار را انجام می‌دهد.

ارسال نظر