ฉันจะสแกนเอาต์พุตขนาดใหญ่ของคำสั่งโดยตรงไปยังเครื่องระยะไกลได้อย่างไร


50

โปรดทราบว่าฉันไม่สามารถจัดเก็บไฟล์ไว้ในเครื่องก่อน - มันใหญ่เกินไป

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

http://webcache.googleusercontent.com/search?q=cache:lhmh960w2KQJ:www.experts-exchange.com/OS/Unix/SCO_Unix/Q_24249634.html+scp+redirect&cd=3&hl=en&ct=clnk&gl=us

หากต้องการทำให้เป็นรูปธรรมมากขึ้นนี่คือวิธีที่คุณคิดว่าอาจใช้งานได้:

บนเครื่องท้องถิ่น:

% echo "pretend this string is a huge amt of data" | scp - remote.com:big.txt

(นั่นคือการใช้การประชุม - scp ที่ไม่สนับสนุนในความเป็นจริง - แทนเส้นประสำหรับไฟล์ต้นฉบับเพื่อบอกให้รับจาก stdin แทน)


คุณสามารถโพสต์ URL ของผลลัพธ์ google ของคุณได้หรือไม่? ผู้เชี่ยวชาญด้านการแลกเปลี่ยนแสดงเฉพาะคำตอบที่ด้านล่างถ้าอ้างอิงของคุณ google ...
จอน

คำตอบ:


76

คุณสามารถไพพ์เข้าสู่ ssh และรันคำสั่งรีโมต ในกรณีนี้คำสั่งระยะไกลcat > big.txtจะทำการคัดลอก stdin ไปยังbig.txtไฟล์

echo "Lots of data" | ssh user@example.com 'cat > big.txt'

มันง่ายและตรงไปตรงมาตราบใดที่คุณสามารถใช้ ssh เพื่อเชื่อมต่อกับปลายระยะไกล

คุณยังสามารถใช้nc(NetCat) เพื่อถ่ายโอนข้อมูล บนเครื่องรับ (เช่น host.example.com):

nc -l 1234 > big.txt

สิ่งนี้จะตั้งค่าncให้ฟังพอร์ต 1234 และคัดลอกสิ่งที่ส่งไปยังพอร์ตนั้นไปยังbig.txtไฟล์ จากนั้นบนเครื่องส่ง:

echo "Lots of data" | nc host.example.com 1234

คำสั่งนี้จะบอกncด้านการส่งเพื่อเชื่อมต่อกับพอร์ต 1234 บนเครื่องรับและคัดลอกข้อมูลจาก stdin ผ่านเครือข่าย

อย่างไรก็ตามncวิธีแก้ปัญหามีข้อเสียเล็กน้อย:

  • ไม่มีการรับรองความถูกต้อง; ทุกคนสามารถเชื่อมต่อกับพอร์ต 1234 และส่งข้อมูลไปยังไฟล์
  • sshข้อมูลที่ไม่ได้เข้ารหัสตามที่มันจะมี
  • หากทั้งสองเครื่องอยู่หลังไฟร์วอลล์พอร์ตที่เลือกจะต้องเปิดเพื่อให้สามารถเชื่อมต่อและกำหนดเส้นทางได้อย่างถูกต้องโดยเฉพาะที่ปลายรับ
  • ปลายทั้งสองจะต้องตั้งค่าอย่างอิสระและพร้อมกัน ด้วยsshวิธีแก้ปัญหาคุณสามารถเริ่มต้นการถ่ายโอนจากหนึ่งในปลายทาง

หากเป็นการปลอบใจใด ๆ ฉันมีแนวโน้มที่จะทำเครื่องหมายว่าคุณยอมรับเพราะอธิบายอย่างชัดเจนว่าเกิดอะไรขึ้น (ถ้าคุณอยากจะกอดจริงๆมันคุณอาจรวมถึงการแก้ปัญหาท่อและ netcat FIFO มีคำแนะนำบางอย่างเกี่ยวกับเหตุผลที่คุณอาจต้องการที่หนึ่งหรืออื่น ๆ :)!
dreeves

เสร็จสิ้น Netcat เป็นเครื่องมือที่มีประโยชน์ :)
Barry Brown

เช่นเดียวกับในความคิดเห็นอื่น ๆ หากคุณกำลังส่งผ่าน tar คุณสามารถใช้การทดแทนกระบวนการ:tar -cvzf >(ssh destination 'cat > file') huge_directory_tree
Taywee

1
SSH เป็นหนทางที่แน่นอน เปรียบเทียบกับncมันยังมีการเข้ารหัสและการบีบอัดข้อมูลของคุณโดยค่าเริ่มต้นและที่สำคัญกว่า: การตรวจจับข้อผิดพลาด ฉันมีสถานการณ์ที่ฉันใช้ncกับไดรเวอร์เครือข่ายผิดพลาดและข้อมูลที่เสียหายถูกส่งไปโดยไม่ถูกตรวจจับ SSH จะล้มเหลวในสถานการณ์นั้นเนื่องจากไม่สามารถถอดรหัส / ถอดรหัสข้อมูลที่ผิดพลาดได้
jlh

15

ใช้ ssh:

echo "pretend this is a huge amt of data" | ssh user@remote.com 'cat > big.txt'

อ่าสวยงามขอบคุณ! เหตุผลใดที่ต้องการโซลูชันนี้หรือโซลูชันท่อ FIFO
สาม

ฉันคิดว่าวิธี mknod ทำให้งานสำเร็จในลักษณะเดียวกันยกเว้นไปป์ที่มีชื่อ
bpf

4

ใช้nc (Net Cat) ซึ่งไม่จำเป็นต้องบันทึกไฟล์ไว้ในเครื่อง


อ้าขอบคุณ! ต้องการรวมตัวอย่าง "echo .. | scp .. " ของฉันหรือไม่ และเหตุผลใดที่คุณรู้ว่าชอบสิ่งนี้กับคำตอบอื่น ๆ
dreeves

2
ฉันขอแนะนำอย่างยิ่งให้ใช้ncกับสิ่งนี้ ฉันเคยทิ้งภาพดิสก์ดิบจากเครื่องหนึ่งไปยังอีกเครื่องหนึ่งเพื่อหาข้อมูลในภายหลังว่าไดรเวอร์เครือข่ายของฉันเกิดข้อผิดพลาดและถ่ายโอนบิตผิดพลาด การใช้งานscp, sshหรือสิ่งอื่นที่จะบอกคุณเมื่อมีข้อผิดพลาดในการส่ง
jlh

2

ใช้ท่อ FIFO:

mknod mypipe p
scp mypipe destination &
ls > mypipe

ฉันไม่สามารถทำให้มันทำงานบนระบบ Linux ได้ scpบ่นว่า mypipe ไม่ใช่ไฟล์ปกติ
Barry Brown

1
ไม่ได้ทำงานบน Mac ด้วยเหตุผลเดียวกัน (ฉันต้องใช้mkfifoเพื่อสร้างไปป์)
Barry Brown

1
ไม่ได้ทำงานที่นี่เช่นกัน แต่ถ้ามันได้ผลสำหรับคุณและคุณมี bash หรือ zsh คุณสามารถทำได้โดยการทดแทนกระบวนการเช่นในตัวอย่างนี้:scp <(ls) destination
Taywee

1

Thanx Denis Scherbakov!

เมื่อฉันลองสคริปต์ของคุณบนคลาวด์ Hetzner ฉันได้รับ

debug1: Sending command: scp -v -t backup-20180420120524.tar.xz.enc
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
Transferred: sent 4168, received 2968 bytes, in 0.0 seconds
Bytes per second: sent 346786.6, received 246944.0

แต่ไฟล์ที่ไม่มีเนื้อหาเท่านั้นที่ถูกสร้างขึ้น เนื่องจากเนื้อหาจริงถูกเข้ารหัสด้วย openssl เราจึงไม่จำเป็นต้องใช้ scp ลินุกซ์ในตัวftpยังมีความสามารถในการวางท่อที่ดีเยี่ยม ดังนั้นนี่คือโซลูชัน (ยังค่อนข้างเป็นคู่มือ) ของฉัน:

#!/bin/bash

function join_e
{
  for word in $*; do
    echo -n "--exclude=$word "
  done
}


# Directory and file inclusion list
ILIST=(
  /home
)

# Directory and file exclusion list
ELIST=(
  var/lib/postgresql
)



export OPASS=fileencryptionpassword

nice -n 19 bash -c \
   "\
   tar $(join_e ${ELIST[@]}) -cpvf - -C / ${ILIST[*]} \
   | xz -c9e -T8 \
   | openssl enc -aes-256-cbc -pass env:OPASS \
   "

# decrypt with:
# cat backup.tar.xz.enc | openssl  aes-256-cbc -d  -pass env:OPASS | xz -dc | tar xv

# invocation procedure for ftp:
# $ ftp -np
# ftp> open storage.com
# ftp> user  storageuser storagepass
# ftp> put "| bash ~/backup.sh" backup.tar.xz.enc

1

นี่คือทางเลือกอื่น:

ตัวอย่างทั้งหมดข้างต้นที่แนะนำ ssh + cat ถือว่า "cat" พร้อมใช้งานบนระบบปลายทาง

ในกรณีของฉันระบบ (การสำรองข้อมูล Hetzner) มีชุดเครื่องมือที่เข้มงวดมากที่เสนอ sftp แต่ไม่ใช่เชลล์ที่สมบูรณ์ ดังนั้นการใช้ ssh + cat จึงเป็นไปไม่ได้ ฉันคิดวิธีแก้ปัญหาที่ใช้แฟล็ก "scp -t" ที่ไม่มีเอกสาร สคริปต์ที่สมบูรณ์อาจพบได้ที่ด้านล่าง

#!/bin/bash

function join_e
{
  for word in $*; do
    echo -n "--exclude=$word "
  done
}

CDATE=`date +%Y%m%d%H%M%S`

# Make password available to all programs that are started by this shell.
export OPASS=YourSecretPasswrodForOpenSslEncryption

#-----------------------------------------------

# Directory and file inclusion list
ILIST=(
  var/lib
)

# Directory and file exclusion list
ELIST=(
  var/lib/postgresql
)

# 1. tar: combine all files into a single tar archive
#      a. Store files and directories in ILIST only.
#      b. Exclude files and directories from ELIST.
# 2. xz: compress as much as you can utilizing 8 threads (-T8)
# 3. openssl: encrypt contents using a password stored in OPASS local environment variable
# 4. cat: concatenate stream with SCP control message, which has to be sent before data
#      a. C0600 - create a file with 600 permissions
#      b. 107374182400 - maximum file size
#         Must be higher or equal to the actual file size.
#         Since we are dealing with STDIN, we have to make an educated guess.
#         I've set this value to 100x times my backups are.
#      c. stdin - dummy filename (unused)
# 5. ssh: connect to the server
#      a. call SCP in stdin (-t) mode.
#      b. specify destination filename

nice -n 19 bash -c \
   "\
   tar $(join_e ${ELIST[@]}) -cpf - -C / ${ILIST[*]} \
   | xz -c9e -T8 \
   | openssl enc -aes-256-cbc -pass env:OPASS \
   | cat <(echo 'C0600 107374182400 stdin') - \
   | ssh username@server.your-backup.de "\'"scp -t backup-${CDATE}.tar.xz.enc"\'"\
   "

อัปเดต 2019.05.08:

ตามคำขอด้านล่างเป็นรุ่นที่ง่ายกว่าและสั้นกว่ามาก

#!/bin/sh

# WORKS ON LARGE FILES ONLY

cat filename.ext \
| cat <(echo 'C0600 107374182400 stdin') - \
| ssh user@host.dom 'scp -t filename.ext'

คุณสามารถปรับปรุงนี้โดยการเอาทุกสิ่งที่ไม่จำเป็นและเพียงแค่ตัดลงนี้กับตัวอย่างขั้นต่ำเปลือยของวิธีการใช้scp -t? ตอนนี้คุณมีสคริปต์ที่สมบูรณ์ที่กำหนดเองสูง / เป็นภาษาท้องถิ่นกับสภาพแวดล้อมของคุณ สิ่งที่ดีสำหรับ Hetzner wiki แต่ไม่ใช่สำหรับ Super User ที่ผู้คนส่วนใหญ่แค่มองหาวิธีการป้อนข้อมูลผ่าน scp
allquixotic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.