วิธีคัดลอกไฟล์ที่ยังเขียนทับ ssh อยู่?


20

นี่คือสถานการณ์:

  1. ฉันกำลังอัปโหลดไฟล์ขนาดใหญ่จากไคลเอนต์ A ไปยังเซิร์ฟเวอร์โดยใช้ sftp
  2. ฉันยังต้องดาวน์โหลดไฟล์นี้จากเซิร์ฟเวอร์ไปยังไคลเอนต์ B ผ่าน ssh

สิ่งที่ฉันต้องการจะทำคือเริ่มการถ่ายโอนจากเซิร์ฟเวอร์ไปยังไคลเอนต์ B เมื่อการอัพโหลดยังคงเกิดขึ้นจากไคลเอนต์ A

วิธี / เครื่องมือที่ดีที่สุดในการทำสิ่งนี้คืออะไร?

อัปเดต :

คำตอบที่น่าสนใจมาก - ฉันจะอ่านและทดสอบพวกเขาทั้งหมด คะแนนโบนัสสำหรับคำตอบที่ไม่ขึ้นอยู่กับการควบคุมว่าลูกค้า A อัพโหลดไฟล์อย่างไร (เช่นสิ่งเดียวที่เรารู้จากลูกค้า A คือไฟล์กำลังถูกเขียนไปยังชื่อไฟล์ที่รู้จัก)


Ooo คำถามที่ดี เป็นไปได้อย่างแน่นอน แต่ฉันไม่ได้ตระหนักถึงสิ่งใดที่ใช้มัน
Michael Mrozek

คำตอบ:


10

สำหรับไฟล์เดียวแทนที่จะใช้ SFTP คุณสามารถไพพ์ไฟล์ผ่าน ssh โดยใช้catหรือpvที่ด้านการส่งและใช้teeบนเซิร์ฟเวอร์กลางเพื่อส่งข้อมูลไปยังไฟล์ที่นั่นและส่งสำเนาไปที่ลิงค์ ssh อีกด้านหนึ่ง เพียงแค่เขียนข้อมูลลงในไฟล์ วูดูต้องใช้ฉันจะออกจากการออกกำลังกายสำหรับผู้อ่านเนื่องจากฉันไม่มีเวลาเล่นตอนนี้ (ขออภัย) วิธีนี้จะใช้ได้ต่อเมื่อปลายทางที่สองนั้นสามารถเข้าถึงได้แบบสาธารณะผ่าน SSH ซึ่งอาจไม่ใช่กรณีที่คุณอธิบายว่าเป็นเครื่องไคลเอนต์

อีกวิธีหนึ่งซึ่งน้อยกว่า "เรียกใช้และรอ" แต่อาจจะง่ายกว่านั้นคือใช้rsyncระหว่างเซิร์ฟเวอร์และไคลเอนต์ B ในครั้งแรกที่คุณเรียกใช้งานนี้อาจได้รับสำเนาบางส่วนของข้อมูล แต่คุณสามารถเรียกใช้ซ้ำได้ เพื่อรับข้อมูลเพิ่มเติมในภายหลัง (ด้วยการเรียกใช้ครั้งสุดท้ายครั้งเดียวเมื่อ Client1-> การถ่ายโอนเซิร์ฟเวอร์เสร็จสมบูรณ์) วิธีนี้จะใช้งานได้หากเซิร์ฟเวอร์ส่งข้อมูลโดยตรงไปยังชื่อไฟล์ที่ถูกต้องระหว่างการถ่ายโอน SFTP (บางครั้งคุณจะเห็นข้อมูลที่เข้าสู่ไฟล์ชั่วคราวซึ่งจะถูกเปลี่ยนชื่อเมื่อโอนไฟล์เสร็จแล้ว - เพื่อทำการ อัปเดตไฟล์มากขึ้น แต่จะทำให้แนวคิด rsync ใช้งานไม่ได้) คุณสามารถใช้ rsync สำหรับการถ่ายโอน C1-> S แทน scp (ถ้าคุณใช้--inplaceตัวเลือกเพื่อหลีกเลี่ยงปัญหาที่กล่าวถึงข้างต้น) - การใช้ rsync จะช่วยป้องกันไม่ให้ส่งทุกอย่างถ้าการเชื่อมต่อเซิร์ฟเวอร์ C1-> ประสบปัญหาระหว่างการถ่ายโอนขนาดใหญ่ (ฉันมักจะใช้rsync --inplace -a --progress <source> <dest>แทน scp / sftp เมื่อ rsync พร้อมใช้งานสำหรับ พฤติกรรม "transfer resume" นี้)

เพื่อสรุปข้างต้นให้เรียกใช้:

rsync --inplace -a --progress <source> user@server:/<destination_file_or_folder>

บน client1 จากนั้นทำงาน

rsync --inplace -a --progress user@server:/<destination_file_or_folder> <destination_on_cli2>

บน client2 ซ้ำ ๆ จนกระทั่งการถ่ายโอนครั้งแรกเสร็จสมบูรณ์ (จากนั้นทำงานอีกครั้งเพื่อให้แน่ใจว่าคุณมีทุกอย่างแล้ว) rsyncทำได้ดีมากในการถ่ายโอนขั้นต่ำที่จำเป็นต้องอัปเดตสถานที่แทนการถ่ายโอนล็อตทั้งหมดในแต่ละครั้ง สำหรับความหวาดระแวงคุณอาจต้องการเพิ่ม--checksumตัวเลือกในคำสั่ง rsync (ซึ่งจะใช้เวลา CPU มากขึ้นสำหรับไฟล์ขนาดใหญ่ แต่จะไม่ส่งผลให้มีการถ่ายโอนข้อมูลมากขึ้นอย่างมีนัยสำคัญหากไม่จำเป็น) และความเร็ว--compressตัวเลือกจะช่วยถ้าข้อมูล คุณกำลังถ่ายโอนไม่ได้อยู่ในรูปแบบการบีบอัด


5

ฉันไม่สามารถลองได้ในขณะนี้ดังนั้นสิ่งนี้อาจล้มเหลว: ความคิดของฉันคือ: ติดตั้งไดเรกทอรีที่ไฟล์มาถึงลูกค้า B เช่นกับ sshfs ถึง / mnt / เซิร์ฟเวอร์ในระบบไฟล์ของลูกค้า b แล้วก็

tail -c +0 -f /mnt/server/thefileinquestion > ~/finalfile

/ usr / bin / tail: ไม่สามารถเปิด `+0 'สำหรับการอ่าน: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว - coreutils 7.4
maxschlepzig

ขออภัยมี -c หายไป ฉันแก้ไขมันในคำตอบข้างต้น
fschmitt

ตกลงปัญหาที่ฉันเห็นคือว่าคำสั่งไม่ยุติ (-f -> follow ... ) หนึ่งต้องออก sigQUIT หรืออะไรทำนองนั้นเมื่อคุณแน่ใจว่า Btw ขึ้นอยู่กับรุ่นท้ายและ fs ของคุณ tail จะทำการสำรวจไฟล์ภายใน (เช่นทุกวินาที)
maxschlepzig

ฉันมีกรณี: การบันทึกไฟล์วิดีโอลงบน HDD ของฉัน แต่ฉันต้องการคัดลอกไปยังหน่วยความจำแฟลช USB ภายนอกเพื่อให้ฉันสามารถส่งมันไปยังบุคคลได้ทันทีที่การบันทึกหยุดลง ฉันลองหลายครั้งrsync --appendแล้วตรวจสอบด้วยmd5sumแต่ไฟล์ไม่เคยตรงกัน tail -c +0ทำงานให้ฉัน ฉันยังใช้pv -pteraในการตรวจสอบความคืบหน้าของหางมันช่วยให้ฉันดูว่ามันทำงาน ฉันยังตรวจสอบ md5s ไม่เสร็จเพื่อยืนยันว่าใช้งานได้ แต่ดูดี
unfa

@unfa โปรดอัปเดตความคิดเห็นของคุณโดยเพิ่มคำตอบด้านล่าง (เช่นไม่ใช่ความคิดเห็น)
Xofo

1

ฉันคิดว่าสิ่งนี้ควรจะได้ผล:

user@clientA:~$ cat file | ssh server "cat > dest"

แล้ว

user@clientB:~$ ssh server "tail +0 -f dest" > file

เพิ่มคำสั่ง pv หากคุณต้องการดูปริมาณงานของคุณ


คุณหมายถึงการเขียนtail -c +0?
ของหวาน

1

คุณสามารถใช้ Fifo ได้ เพื่อความง่ายก่อนโดยไม่ต้อง ssh เกี่ยวข้องกับสอง xterms:

ที่ xterm A:

$ mkfifo fif
$ cat test.tar.gz | tee copy.tar.gz > fif

ที่ xterm B:

$ cat fif > dest.tar.gz
$ cmp test.tar.gz dest.tar.gz
$ echo $?
0
$ cmp test.tar.gz copy.tar.gz
$ echo $?
0

ด้วย ssh มันควรจะมีบางอย่างตามบรรทัดเหล่านี้ - บางทีคุณต้องปิดการใช้งาน escape-character ใน ssh (-e none):

ลูกค้า A:

 $ ssh server mkfifo fif
 $ cat src.tar.gz | ssh "tee fif > copy.tar.gz"

ลูกค้า B:

 $ ssh server cat fif > dest.tar.gz

1

ฉันมีสถานการณ์ที่ต้องการคำตอบเหมือนโปสเตอร์ต้นฉบับที่ถาม ฉันกำลังบันทึกเกมฮ็อกกี้บนคอมพิวเตอร์ของฉันในที่เดียวและฉันต้องการดูบนทีวีของฉันที่ตำแหน่งอื่น ลิงก์ระหว่างสถานที่ทั้งสองอนุญาตให้คัดลอกได้ที่ประมาณ 1.3Mb / s และวิดีโอการบันทึกประมาณ 1.5Mb / s ดังนั้นฉันต้องการคัดลอกไฟล์เมื่อเริ่มบันทึก วิธีนี้เกม 3 ชั่วโมงของฉันจะคัดลอกในเวลาประมาณ 3.5 ชั่วโมง ดังนั้นฉันจึงคัดลอกเมื่อเริ่มบันทึกและฉันสามารถเริ่มดูได้ 30 นาทีหลังจากเริ่ม จากนั้นฉันสามารถดูได้โดยไม่หยุดชะงักเกือบตามเวลาจริง นั่นคือตราบใดที่ฉันยังสามารถคัดลอกได้เมื่อมันเขียนไฟล์ใหม่ ปัญหาเกี่ยวกับเครื่องมือเช่น rsync และ scp คือพวกเขาดูขนาดของไฟล์เมื่อคุณเริ่มต้นการคัดลอกและเมื่อมันทำการคัดลอกจำนวนข้อมูลนั้นมันจะหยุดทำงาน แม้ว่าไฟล์จะเพิ่มขึ้นมากกว่าสองเท่าในระหว่างการคัดลอก และถ้าฉันเพียงแค่ใช้ rsync ในการวนเพื่อคัดลอกเมื่อมันหยุดเมื่อ rsync ถัดไปเสร็จสิ้นมันจะสร้างไฟล์เป้าหมายและฆ่าเครื่องเล่นวิดีโอของฉันและฉันต้องรีสตาร์ทดูและไปข้างหน้าอย่างรวดเร็วไม่ว่าฉันจะอยู่ที่ไหน ในโปรแกรมเมื่อมันฆ่ามันทันที ฉันต้องการทางออกที่ดีกว่าและฉันไม่สามารถหาได้ดังนั้นฉันจึงรวบรวมสิ่งนี้ไว้แทน:

dd if=2031_20160514030000.mpg |
pv --size 4653819304 |
ssh -C -c arcfour,blowfish-cbc -p 5555 myserver.com 'dd of=/media/TV/2031_20160514030000.mpg'

แล้วมันจะทำอะไร?

ก่อนอื่นฉันใช้ dd เพื่อคัดลอกไฟล์เมื่อขยาย เนื่องจากไฟล์เติบโตเร็วกว่า dd สามารถส่งผ่านเครือข่ายได้ dd จะไม่จับจนถึงจุดสิ้นสุดของไฟล์ ต่อไปฉันไปป์กับ "ไปป์ที่วิว (pv)" และฉันให้มันประเมินว่าไฟล์จะใหญ่แค่ไหนขึ้นอยู่กับว่าไฟล์เหล่านี้ใหญ่แค่ไหน ไม่จำเป็น แต่ฉันอยากเห็นตัววัดความก้าวหน้า จากนั้นฉันจะสตรีมไปยังการเชื่อมต่อ ssh ของฉัน ใช้การเชื่อมต่อ SSH -Cสำหรับการบีบอัด (เพื่อลดแบนด์วิธเครือข่ายและพยายามที่จะเพิ่มความเร็วขึ้น) -c arcfour,blowfish-cbcสำหรับการเข้ารหัสอย่างน้อยราคาแพง (อีกครั้งกับสิ่งความเร็วขึ้นเล็กน้อย) ที่-pสำหรับพอร์ตไฟร์วอลล์ของฉันที่ฉันใช้ที่ปลายทางและในที่สุด ssh จะรันคำสั่ง dd บนเป้าหมายเพื่อสร้างไฟล์ขึ้นใหม่ตามที่ได้รับ ฉันยินดีที่จะบอกว่าวิธีนี้ใช้งานได้ดี ฉันสามารถดูเกมฮ็อคกี้ในขณะที่สร้างและคัดลอกไฟล์ได้ในเวลาอันสั้น


0

ฉันไม่แน่ใจว่าวิธี tail -f ใช้งานได้ (แม้ว่ามันจะเป็นเช่นนั้นหากไฟล์เป็นข้อความ) เหตุผลก็คือฉันไม่ทราบว่า tail -f และการถ่ายโอน sftp และพึ่งพาข้อมูลเมตา

หาก sftp ถ่ายโอนข้อมูลเมตาก่อนและ tail -f อาศัยข้อมูลเมตาเพื่อบอกว่าไม่มีไฟล์อีกต่อไปส่วนท้ายอาจทำให้จุดสิ้นสุดด้วย EOFs หรือ null

หากคุณไม่สนใจเกี่ยวกับเส้นทางของการอัปโหลดเช่นคอมพิวเตอร์ 1 อัปโหลดไปยังคอมพิวเตอร์ 2 อัปโหลดไปยังคอมพิวเตอร์ 3 คุณอาจลองใช้ bittorent แทน top แทน sftp ดูเหมือนว่าเป็นสิ่งที่ออกแบบมาสำหรับ


0

คุณสามารถลองอ่านไฟล์ได้ตั้งแต่ต้น แต่คุณต้องแน่ใจว่าคุณสามารถเขียนมันด้วยความเร็วเดียวกันอย่างน้อยที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.