المرسل والمتلقي لنقل الملفات عبر SSH عند الطلب؟
-
21-08-2019 - |
سؤال
لقد قمت بإنشاء برنامج يتكرر على مجموعة من الملفات ويستدعي بعضها:
scp <file> user@host:<remotefile>
ومع ذلك، في حالتي، قد يكون هناك الآلاف من الملفات الصغيرة التي تحتاج إلى النقل، ويقوم scp بفتح اتصال ssh جديد لكل منها، الأمر الذي ينطوي على بعض الحمل الزائد.
كنت أتساءل عما إذا كان لا يوجد حل حيث أحافظ على تشغيل عملية واحدة تحافظ على الاتصال ويمكنني إرسال "طلبات" للنسخ عبر ملفات فردية.
من الناحية المثالية، أبحث عن مجموعة من برامج المرسل والمستقبل، بحيث يمكنني بدء عملية واحدة (1) في البداية:
ssh user@host receiverprogram
ولكل ملف، أقوم باستدعاء الأمر (2):
senderprogram <file> <remotefile>
وقم بتوصيل مخرج (2) إلى مدخل (1)، وهذا من شأنه أن يتسبب في نقل الملف.في النهاية، يمكنني فقط إرسال إشارة معينة للإنهاء للعملية (1).
ويفضل أن تكون برامج المرسل والمستقبل برامج C مفتوحة المصدر لنظام Unix.وقد يتواصلون باستخدام مقبس بدلاً من الأنبوب، أو أي حل إبداعي آخر.
ومع ذلك، فهو قيد مهم أن يتم نقل كل ملف في اللحظة التي أكرر فيها:ليس من المقبول جمع قائمة بالملفات ثم استدعاء مثيل واحد منها scp
لنقل جميع الملفات مرة واحدة في النهاية.أيضًا، ليس لدي سوى وصول بسيط إلى المضيف المتلقي.
تحديث: لقد وجدت حلاً لمشكلة حمل الاتصال باستخدام ميزات تعدد الإرسال في ssh، راجع إجابتي الخاصة أدناه.ومع ذلك، فقد بدأت في إنشاء مكافأة لأنني أشعر بالفضول لمعرفة ما إذا كان هناك برنامج مرسل/مستقبل كما أصفه هنا.يبدو أنه يجب أن يكون هناك شيء يمكن استخدامه، على سبيل المثال.xmodem/ymodem/zmodem؟
المحلول
قد تنجح هذه الطريقة، وبالنسبة لأشياء أخرى، فإن هذا النهج العام هو الصحيح إلى حد ما.
(
iterate over file list
for each matching file
echo filename
) | cpio -H newc -o | ssh remotehost cd location \&\& | cpio -H newc -imud
نصائح أخرى
لقد وجدت الحل من زاوية أخرى.منذ الإصدار 3.9, ، يدعم OpenSSH مضاعفة الجلسة:يمكن أن يحمل اتصال واحد عدة جلسات تسجيل دخول أو نقل ملفات.وهذا يتجنب تكلفة الإعداد لكل اتصال.
بالنسبة لحالة السؤال، يمكنني أولاً فتح اتصال من خلال إعداد عنصر التحكم الرئيسي (-M
) مع مأخذ (-S
) في مكان محدد.لا أحتاج إلى جلسة (-N
).
ssh user@host -M -S /tmp/%r@%h:%p -N
بعد ذلك، يمكنني الاستدعاء scp
لكل ملف وإرشاده لاستخدام نفس المقبس:
scp -o 'ControlPath /tmp/%r@%h:%p' <file> user@host:<remotefile>
يبدأ هذا الأمر في النسخ على الفور تقريبًا!
يمكنك أيضًا استخدام مقبس التحكم لاتصالات ssh العادية، والتي سيتم فتحها على الفور:
ssh user@host -S /tmp/%r@%h:%p
إذا لم يعد مقبس التحكم متاحًا (على سبيل المثال.لأنك قتلت السيد)، فهذا يعود إلى الاتصال الطبيعي.مزيد من المعلومات متاحة في هذا المقال.
قد يكون من المفيد استخدام sftp بدلاً من scp، ووضعه في الوضع الدفعي.اجعل ملف الأمر الدفعي عبارة عن أنبوب أو مقبس مجال UNIX وأوامر التغذية إليه كما تريد تنفيذها.
قد يكون الأمان في هذا الأمر صعبًا بعض الشيء من جانب العميل.
هل جربت sshfs
؟يمكنك:
sshfs remote_user@remote_host:/remote_dir /mnt/local_dir
أين
/remote_dir
كان هو الدليل الذي تريد إرسال الملفات إليه على النظام الذي تنتقل إليه/mnt/local_dir
كان موقع التثبيت المحلي
مع هذا الإعداد يمكنك فقط cp
ملف في local_dir
وسيتم إرسالها sftp
ل remote_host
فيه remote_dir
لاحظ أن هناك اتصالًا واحدًا، لذلك لا يوجد سوى القليل من الحمل
قد تحتاج إلى استخدام العلم -o ServerAliveInterval=15
للحفاظ على اتصال غير محدد
سوف تحتاج إلى أن يكون لديك fuse
تم تثبيته محليًا ودعم خادم SSH (وتكوينه من أجل) sftp
ربما كنت تبحث عن هذا:ZSSH
zssh (Zmodem SSH) هو برنامج لنقل الملفات بشكل تفاعلي إلى جهاز بعيد أثناء استخدام الغلاف الآمن (ssh).الغرض منه هو أن يكون بديلاً مناسبًا لـ scp، مما يسمح بنقل الملفات دون الحاجة إلى فتح جلسة أخرى وإعادة المصادقة.
استخدم rsync عبر ssh إذا كان بإمكانك جمع كل الملفات لإرسالها في دليل واحد (أو التسلسل الهرمي للأدلة).
إذا لم يكن لديك جميع الملفات في مكان واحد، فيرجى تقديم بعض المعلومات الإضافية حول ما تريد تحقيقه ولماذا لا يمكنك تجميع جميع الملفات في الأرشيف وإرسالها.لماذا من المهم جدًا إرسال كل ملف على الفور؟هل سيكون من المقبول إذا تم إرسال الملف بتأخير قصير (مثلاً عند تراكم بيانات بقيمة 4K)؟
إنها مشكلة صغيرة لطيفة.لست على علم بوجود حل مُجهز مسبقًا، ولكن يمكنك فعل الكثير باستخدام نصوص shell البسيطة.سأحاول هذا على المتلقي:
#!/bin/ksh
# this is receiverprogram
while true
do
typeset -i length
read filename # read filename sent by sender below
read size # read size of file sent
read -N $size contents # read all the bytes of the file
print -n "$contents" > "$filename"
done
من جانب المرسل، أقوم بإنشاء أنبوب مسمى وأقرأ من الأنبوب، على سبيل المثال،
mkfifo $HOME/my-connection
ssh remotehost receiver-script < $HOME/my-connection
ثم لإرسال ملف سأجرب هذا البرنامج النصي
#!/bin/ksh
# this is senderprogram
FIFO=$HOME/my-connection
localname="$1"
remotename="$2"
print "$remotename" > $FIFO
size=$(stat -c %s "$localname")
print "$size" > $FIFO
cat "$localname" > $FIFO
إذا كان حجم الملف كبيرًا، فمن المحتمل أنك لا ترغب في قراءته مرة واحدة، لذا يجب أن يكون هناك شيء ما
BUFSIZ=8192
rm -f "$filename"
while ((size >= BUFSIZ)); do
read -N $BUFSIZE buffer
print -n "$buffer" >> "$filename"
size=$((size - BUFSIZ))
done
read -N $size buffer
print -n "$contents" >> "$filename"
في النهاية ستحتاج إلى توسيع البرنامج النصي حتى تتمكن من المرور chmod
و chgrp
الأوامر.نظرًا لأنك تثق في رمز الإرسال، فقد يكون من الأسهل هيكلة الشيء بحيث يقوم المتلقي باستدعاء الصدفة ببساطة eval
على كل سطر، ثم أرسل أشياء مثل
print filename='"'"$remotename"'"' > $FIFO
print "read_and_copy_bytes " '$filename' "$size" > $FIFO
ومن ثم تحديد وظيفة محلية read_and_copy_bytes
.الحصول على الاقتباس الصحيح هو أمر دب، ولكن بخلاف ذلك يجب أن يكون واضحًا.
وبطبيعة الحال، لم يتم اختبار أي من هذا!ولكن آمل أن يعطيك بعض الأفكار المفيدة.
يبدو وكأنه وظيفة للقطران؟قم بتوصيل مخرجاته إلى ssh، وعلى الجانب الآخر قم بتوصيل مخرجات ssh مرة أخرى إلى tar.
أعتقد أن سطح مكتب جنوم يستخدم اتصال SSH واحدًا عند الوصول إلى مشاركة عبر SFTP (SSH).أعتقد أن هذا ما يحدث لأنني أرى عملية SSH واحدة عندما أقوم بالوصول إلى مشاركة عن بعد بهذه الطريقة.لذا، إذا كان هذا صحيحًا، فيجب أن تكون قادرًا على استخدام نفس البرنامج لهذا الغرض.
يستخدم الإصدار الجديد من جنوم GVFS من خلال جيو من أجل تنفيذ جميع أنواع الإدخال/الإخراج من خلال واجهات خلفية مختلفة.توفر حزمة Ubuntu gvfs-bin العديد من الأدوات المساعدة لسطر الأوامر التي تتيح لك التعامل مع الواجهات الخلفية من سطر الأوامر.
ستحتاج أولاً إلى تحميل مجلد SSH الخاص بك:
gvfs-mount sftp://user@host/
وبعد ذلك يمكنك استخدام نسخة gvfs لنسخ ملفاتك.أعتقد أنه سيتم تنفيذ جميع عمليات نقل الملفات من خلال عملية SSH واحدة.يمكنك حتى استخدام ps لمعرفة العملية التي يتم استخدامها.
إذا كنت تشعر بالمزيد من المغامرة، فيمكنك أيضًا كتابة برنامجك الخاص بلغة C أو بلغة أخرى عالية المستوى توفر واجهة برمجة التطبيقات لـ GIO.
خيار واحد هو محارة هو تطبيق عميل وخادم SSH مكتوب بلغة Python باستخدام ملتوي نطاق.يمكنك استخدامه لكتابة أداة تقبل الطلبات عبر بعض البروتوكولات الأخرى (مآخذ مجال HTTP أو Unix أو FTP أو SSH أو أي شيء آخر) وتقوم بتشغيل عمليات نقل الملفات عبر اتصال SSH طويل الأمد.في الواقع، لدي العديد من البرامج قيد الإنتاج التي تستخدم هذه التقنية لتجنب عمليات إعداد اتصال SSH المتعددة.
كان يوجد سؤال مشابه جدا هنا منذ أسبوعين.ال إجابة مقبولة يُقترح فتح نفق عند الاتصال بالجهاز البعيد واستخدام هذا النفق لعمليات نقل scp.
ربما CurlFTPFS قد يكون حلا صالحا بالنسبة لك.
يبدو أنه يقوم فقط بتثبيت مجلد كمبيوتر خارجي على جهاز الكمبيوتر الخاص بك عبر SFTP.بمجرد الانتهاء من ذلك، يجب أن تكون قادرًا على استخدام منتجك العادي cp
الأوامر وكل شيء سيتم بشكل آمن.
لسوء الحظ لم أتمكن من اختباره بنفسي، ولكن اسمحوا لي أن أعرف إذا كان يعمل بالنسبة لك!
تحرير 1: لقد تمكنت من تنزيله واختباره.كما كنت أخشى أن الأمر يتطلب أن يكون لدى العميل خادم FTP. لكن, لقد وجدت برنامجًا آخر له نفس المفهوم تمامًا الذي تبحث عنه. sshfs
يسمح لك بالاتصال بجهاز الكمبيوتر العميل الخاص بك دون الحاجة إلى أي خادم خاص.بمجرد قيامك بتثبيت أحد المجلدات الخاصة بهم، يمكنك استخدام الملف العادي cp
أوامر لنقل أي ملفات تحتاجها أكثر.بمجرد الانتهاء من ذلك، ينبغي أن يكون الأمر ابتسامة umount /path/to/mounted/folder
.اسمحوا لي أن أعرف كيف يعمل بها!
rsync -avlzp user@remotemachine:/path/to/files /path/to/this/folder
سيستخدم هذا SSH لنقل الملفات بطريقة غير بطيئة
اجعل الأمر بسيطًا، اكتب نصًا مجمعًا صغيرًا يفعل شيئًا كهذا.
- قطران الملفات
- أرسل ملف القطران
- untar على الجانب الآخر
شيء من هذا القبيل:
- ملفات tar -cvzf test.tgz ....
- scp test.tgz user@other.site.com:.
- ssh user@other.site.com tar -xzvf test.tgz
/جوهان