Relayium

مزامنة مجلد كبير بين خادمين (قابلة للاستئناف، في الخلفية)

آخر تحديث: 2026-08-05

لديك مجلد كبير — عشرات الغيغابايتات — على خادم وتريد نسخة مطابقة على آخر. لا يمكنك مراقبة طرفية لساعات، ولا ينبغي لنقلٍ يموت في منتصف الطريق أن يبدأ من الصفر. صُمِّم relayium sync لهذا: مرآة تزايدية أحادية الاتجاه تتخطى ما هو موجود سلفًا، وتستأنف ملفًا أُرسِل نصفه من حيث توقف، وتتحقق من كل ملف تُرسِله من الطرف إلى الطرف.

يُعِدّ هذا الدليل نقلًا دون إشراف يُصلِح نفسه: فوِّض المُرسِل مرةً واحدة، وشغّل المُستمِع في الخلفية، وقُد relayium sync من حلقة إعادة محاولة داخل tmux كي يستمر عبر الانقطاعات حتى يصل المجلد كاملًا.

لماذا يناسب relayium sync هذه المهمة

sync مرآة تزايدية أحادية الاتجاه عبر البروتوكول الأصلي (ثبّت relayium على الطرفين). ثلاث خصائص تجعله آمنًا للتشغيل وإعادة التشغيل دون إشراف:

المتطلبات المسبقة

ما تحتاج إليه

  • يستخدم هذا الدليل daemon direct (relayium://)، فلا يحتاج الخادمان إلى وصول SSH أحدهما للآخر.
  • افتح منفذ المُستمِع (9031 افتراضيًا) للمُرسِل على الجدار الناري أو مجموعة الأمان لدى المُستقبِل.
  • مساحة تكفي المجلد كاملًا على المُستقبِل. قارِن du -sh /root/workspace على المُرسِل بـ df -h /root على المُستقبِل قبل أن تبدأ نقلًا يستغرق ساعات.

ثبّت relayium على كلا الخادمين (sync يتحدث البروتوكول الأصلي، فيجب أن يكون حاضرًا على كل طرف):

# على كلا الخادمين
curl -fsSL https://relayium.com/install.sh | sh

فوِّض المُرسِل مرةً واحدة (على المُستقبِل)

يعتمد المُستقبِل الجهاز المُرسِل مرةً واحدة؛ يُكتَب الاعتماد على القرص ويبقى صالحًا عبر إعادات التشغيل، فلا تكرره أبدًا. شغّل المُستمِع أولًا في طرفية في المقدمة، ووجِّه --dir إلى الدليل الأب — relayium sync /root/workspace يُعيد إنتاج workspace/... لدى المُستقبِل، فـ --dir /root يُنزِل الملفات في /root/workspace/.

عند أول اتصال للمُرسِل (القسم التالي)، يُظهِر serve عنوانه وبصمته ويطلب منك اعتماده؛ أجِب بـ y فيُحفَظ إلى الأبد:

# على المُستقبِل (في المقدمة، للاعتماد تفاعليًا)
relayium serve --dir /root --port 9031
# على المُستقبِل، عند أول اتصال:
Incoming push from 203.0.113.9:52140
  fingerprint: 9f2c41ab…
Accept and remember this peer? [y/N] y

شغّل المُستمِع في الخلفية (على المُستقبِل)

بمجرد اعتماد البصمة، أوقِف serve الذي في المقدمة (Ctrl-C) وأعِد تشغيله منفصلًا كي يصمد بعد خروجك من الجلسة. يحمّل البصمة المحفوظة ويقبل المُرسِل بصمت — لا مُطالبة هذه المرة. ويسجّل السطر نفسه مُعرّف العملية الجديدة (PID) في ~/relayium-serve.pid، وبه توقِف الخطوة الأخيرة من هذا الدليل المُستمِع الذي شغّلته هي، بدل مطابقة كل أمر relayium على الجهاز:

# على المُستقبِل
nohup relayium serve --dir /root --port 9031 > ~/relayium-serve.log 2>&1 & echo $! > ~/relayium-serve.pid

شغّل sync في حلقة إعادة محاولة تحت tmux (على المُرسِل)

تُقطَع عمليات النقل الطويلة — جلسة تسقط، شبكة متذبذبة، إعادة إقلاع. الحل ليس أداة متطورة؛ بل حلقة تعيد تشغيل sync حتى ينجح، مع مُعدِّد طرفيات كي يصمد بعد خروجك. هنا tmux أنظف من nohup: لا إعادة توجيه مخرجات يمكن أن تُخطئ فيها، ويمكنك إعادة الوصل لمتابعة التقدم.

ابدأ جلسة tmux، ثم شغّل المرآة في حلقة until — تعيد المحاولة كل 10 ثوانٍ حتى يُرجِع sync نجاحًا، ثم تخرج من تلقاء نفسها:

  1. افتح جلسة tmux على المُرسِل كي تعيش الحلقة أطول من جلسة ssh التي شغّلتها منها.

    # على المُرسِل
    tmux new -s xfer      # نفّذ apt install -y tmux إن لم يكن موجودًا
  2. شغّل المرآة داخل حلقة until. تعيد المحاولة كل 10 ثوانٍ حتى ينجح sync، ثم تنتهي من تلقاء نفسها.

    until relayium sync /root/workspace relayium://203.0.113.43:9031; do echo "$(date) retrying"; sleep 10; done
  3. افصِل بـ Ctrl-b ثم d. تظل الحلقة تعمل، وأعِد الوصل متى شئت لتراقبها.

    tmux attach -t xfer

كيف تبدو جولة ناجحة

تطبع كل جولة سطرًا لكل ملف أرسلته فعلًا، ثم سطر ملخّص يقابل ما أُرسِل بما كان لدى المُستقبِل سلفًا. وتنتهي الحلقة عند أول نجاح لـ sync، وذلك الملخّص هو حال المرآة.

relayium sync /root/workspace relayium://203.0.113.43:9031
  workspace/data/part-004.bin (1073741824 bytes)
synced: 1 sent, 812 unchanged

التحقق والإنهاء

يكتمل النقل حين تنتهي حلقة until وتعود إلى مُطالبة صدفة عادية. تأكد من تطابق الطرفين، ثم أوقِف المُستمِع:

  1. انتظر حتى تنتهي حلقة until من تلقاء نفسها. عودتك إلى مِحَث صَدَفة عادي تعني أن النقل انتهى، لا أنك قطعته.

  2. قارِن الإجماليات على كلا الخادمين.

    # قارِن الإجماليات على كلا الخادمين
    du -sh /root/workspace
  3. أوقِف المُستمِع على المُستقبِل بعد تطابق الإجماليات. تُرسَل الإشارة إلى مُعرّف العملية الذي دوّنته عند التشغيل، لا إلى كل أمر relayium على الجهاز بمطابقة نصية، ولا يُحذَف ملف الـPID إلا إذا نجحت تلك الإشارة. وقد يشير ملف PID بقي من تشغيل سابق إلى مُعرّف أعاد النظام استخدامه، فإن لم تكن واثقًا أنه ما زال ملفك، اعرض أولًا سطر أوامر ذلك المُعرّف ولا تقتله إلا إذا ظهر serve.

    # على المُستقبِل، بعد التحقق
    ps -p "$(cat ~/relayium-serve.pid)" -o command=
    kill "$(cat ~/relayium-serve.pid)" && rm ~/relayium-serve.pid

كيف تبدو المرآة المكتملة

يُبلِغ du -sh بالمجموع نفسه على الخادمين، وقد أعادتك حلقة until إلى مِحَث صَدَفة عادي بدل أن تعيد المحاولة من جديد. وتطابُق المجموع فحصٌ خشِن للاكتمال لا برهانٌ على السلامة: فقد قرّر sync بالحجم وmtime أي الملفات لا تُرسَل، فلا يقول المجموع شيئًا عن محتوى الملفات المتخطّاة.

# the same total, on BOTH servers
46G	/root/workspace

استكشاف الأخطاء وإصلاحها

ستة أمور تظهر في مرآة تستغرق ساعات. ثلاثة منها تبدو أعطالًا وليست كذلك، والثلاثة الأخرى أعطال حقيقية، ولكل واحد أمر يخبرك أيَّها تنظر إليه.

العَرَض، الفحص، الإصلاح

لم يُطبَع شيء منذ وقت طويل ويبدو النقل متوقفًا.
# على المُرسِل، مرتين بفارق ثوانٍ قليلة
ss -tinp dst :9031
# ESTAB    وصلت إلى المُستمِع، وليس دليلًا على أن البايتات تتحرك
# SYN-SENT لا يصل إلى المُستمِع

لا يُطبَع التقدم إلا عند اكتمال ملف، فينتقل ملف كبير واحد في صمت تام. ولا تثبت ESTAB إلا إمكانية الوصول، فالمقبس المُنشأ قد يبقى خاملًا أو متعطّلًا، وهي وحدها ليست دليلًا على التقدّم أبدًا. نفّذ الفحص مرتين بفارق ثوانٍ قليلة وقارِن عدّاد bytes_acked الذي يطبعه ‎-i‎ لذلك المقبس: تزايُده يعني نقلًا يتقدّم، وثباته يعني تعطّلًا حقيقيًا.

يبقى المقبس في حالة SYN-SENT ولا يبدأ النقل أصلًا.
# على المُستقبِل
sudo ufw allow from 203.0.113.9 to any port 9031 proto tcp
ss -tlnp | grep 9031

المنفذ محجوب. لا تفتح 9031/TCP إلا أمام المُرسِل — استبدِل 203.0.113.9 بعنوان المُرسِل نفسه، عنوانه العام أو الخاص إن كان الخادمان على الشبكة ذاتها — وضيِّق مجموعة الأمان السحابية على المصدر نفسه، ثم تأكّد من أن serve يستمع فعلًا. هذا أكثر أسباب النقل الذي لا يبدأ شيوعًا.

بعد لصق أمر التشغيل في الخلفية، تبقى الصَدَفة عند مِحَث المتابعة <.
tmux new -s xfer
until relayium sync /root/workspace relayium://203.0.113.43:9031; do echo "$(date) retrying"; sleep 10; done

أمر nohup متعدد الأسطر فيه علامات اقتباس وإعادة توجيه ينكسر عادةً عند إعادة التوجيه لحظة اللصق. استخدم tmux مع حلقة السطر الواحد هذه بدلًا من ذلك: لا إعادة توجيه لتخطئ فيها، ويمكنك إعادة الوصل لتراقب.

قتل التنظيف شيئًا لم تكن تقصده.
pgrep -af relayium
ps -p "$(cat ~/relayium-serve.pid)" -o command=
tmux kill-session -t xfer
kill "$(cat ~/relayium-serve.pid)" && rm ~/relayium-serve.pid

القتل بمطابقة نمط في سطر الأوامر يُرسِل الإشارة إلى كل عملية يحتوي سطر أوامرها ذلك النص، وعلى جهاز يعمل عليه أكثر من نقل واحد لن تكون هي المقصودة. كما أنه لا يوقف المرآة: الحلقة until هي التي تملك sync، فالابن المقتول يُعاد تشغيله بعد عشر ثوانٍ. انظر أولًا بـ pgrep -af، ثم أنهِ ما يملكه هذا الدليل فعلًا — ينهي tmux kill-session -t xfer الحلقة، ويوقف kill على الـPID الموجود في ~/relayium-serve.pid المُستمِع الذي شغّلته. وإن كان ملف الـPID باقيًا من تشغيل سابق، فاعرض سطر أوامره قبل إرسال الإشارة، لأن مُعرّفًا أعاد النظام استخدامه يخص شيئًا آخر تمامًا.

تريد استثناء مجلد فرعي واحد ولا توجد راية استثناء.
relayium sync /root/workspace/src /root/workspace/data relayium://203.0.113.43:9031

يقبل sync الرايتين -i و-p و--delete و--watch و--config-dir، ولا شيء فيها يرشّح مسارًا في وسط الشجرة. سمِّ المجلدات الفرعية التي تريدها بدلًا من ذلك: يصل كل مصدر تحت --dir لدى المُستقبِل باسمه هو، فمع serve --dir /root/workspace يعيد هذا الأمر بناء /root/workspace/src و/root/workspace/data ولا يمشي أبدًا في بيئة venv يمكن إعادة توليدها.

يصل مصدر كنت تتوقع نسخه فارغًا.
relayium sync ./links relayium://203.0.113.43:9031
# warning: no regular files to send (symlinks and special files are skipped)

لا ينقل sync إلا الملفات العادية، وهذا التحذير هو تمامًا شكل شجرة ليس فيها سوى روابط رمزية. وجّه sync إلى المجلدات التي تشير إليها الروابط، وأنشئ ما تحتاج إليه من روابط رمزية على المُستقبِل على حدة.

الأسئلة الشائعة

ماذا يحدث إذا انقطع النقل في منتصف الطريق؟

لا يُفقَد شيء. أعِد تشغيل relayium sync — يتخطى الملفات الموجودة سلفًا لدى المُستقبِل ويستأنف الملف المُرسَل نصفه من إزاحة البايت الموجودة سلفًا على القرص. حلقة until في هذا الدليل تفعل ذلك تلقائيًا حتى تُنسَخ صورة المجلد كاملة.

بماذا يختلف هذا عن rsync؟

كلاهما يقوم بمرآة تزايدية أحادية الاتجاه، لكن relayium sync يعمل عبر اتصال TLS مُثبَّت دون الحاجة إلى حساب SSH (daemon direct)، ويصادق الجهازين ببصمة الشهادة، ويتحقق بـ SHA-256 من كل ملف يَنقُله. وكما في سلوك rsync الافتراضي، يُتخطّى الملف الذي يتطابق حجمه وmtime أصلًا على الطرف المستقبِل بدل إعادة حساب بصمته. إنه محرك النقل نفسه المُستخدَم في أوضاع relayium الأخرى.

هل يحذف sync لدى المُستقبِل الملفات التي أزلتها من المصدر؟

فقط إن طلبت ذلك. افتراضيًا، يضيف sync ويحدّث فقط. مرِّر --delete لعكس عمليات الحذف، ويجب أن يشغّل المُستقبِل serve مع --allow-delete كي يُحترَم ذلك — وإلا يُتجاهَل الحذف ويُبلَّغ عنه.

هل يمكنني إبقاء مجلدين متزامنين باستمرار؟

نعم. أضِف --watch فيبقى sync شغّالًا، مُعيدًا عكس الصورة عند أي تغيير تحت المصدر. لنقل مجلد كبير لمرة واحدة لا تحتاجه — تكفي حلقة إعادة المحاولة مع sync بسيط.

هل عليّ فتح منفذ؟

لـ daemon direct، نعم — يجب أن يكون منفذ المُستمِع (9031 افتراضيًا) قابلًا للوصول من المُرسِل. إن كنت تفضّل عدم فتح منفذ ولديك SSH بين الخادمين سلفًا، فإن sync يعمل أيضًا عبر SSH: relayium sync /path user@host:/path (يجب تثبيت relayium على الطرف البعيد).

انسخ صورة مجلد بين خادمين من خوادمك — تزايديًا، قابلًا للاستئناف، دون ملازمة.

احصل على CLI

تابِع القراءة