ฉันสามารถไปป์ stdout บนเซิร์ฟเวอร์หนึ่งเพื่อ stdin บนเซิร์ฟเวอร์อื่นได้หรือไม่


74

stdoutบนเซิร์ฟเวอร์ CentOS หนึ่งเซิร์ฟเวอร์ต้องถูกไพพ์ไปstdinยังเซิร์ฟเวอร์ CentOS อื่น เป็นไปได้ไหม

ปรับปรุง

ScottPack, MikeyB และ jofel ล้วนมีคำตอบที่ถูกต้อง ฉันได้รับคำตอบให้กับสกอตต์เพราะแม้ว่าคำถามของฉันไม่ได้ระบุความปลอดภัยเป็นข้อกำหนด แต่ก็ดีที่จะปลอดภัย อย่างไรก็ตามคำแนะนำของเพื่อนอีกสองคนนั้นก็ใช้ได้เช่นกัน


1
เป็นที่น่าสังเกตว่าข้อได้เปรียบที่สำคัญของวิธีการที่ไม่ใช่ ssh คือความเร็วในการรับส่งข้อมูล หากคุณอยู่บนเครือข่ายที่รวดเร็วและการรักษาความปลอดภัยไม่จำเป็นนี่อาจคุ้มค่ากับความไม่สะดวกที่เพิ่มขึ้นของการพิมพ์สองคำสั่งในสองหน้าต่าง
Random832

คำตอบ:


94

นี่คือไม่สะท้านใช่

เมื่อหนึ่งใช้sshในการดำเนินการคำสั่งบนเซิร์ฟเวอร์ระยะไกลจะดำเนินการเปลี่ยนเส้นทางภายในอินพุต / เอาท์พุตแฟนซีบางชนิด ที่จริงแล้วฉันพบว่านี่เป็นหนึ่งในคุณสมบัติที่ดีกว่าของ OpenSSH หากคุณใช้sshเพื่อรันคำสั่งตามอำเภอใจบนระบบรีโมต ssh จะแม็พSTDINและSTDOUTกับคำสั่งที่ถูกเรียกใช้งาน

สำหรับวัตถุประสงค์ของตัวอย่างสมมติว่าคุณต้องการสร้าง tarball สำรอง แต่ไม่ต้องการหรือไม่สามารถเก็บไว้ในเครื่องได้ ลองมาดูที่ไวยากรณ์นี้กัน:

$ tar -cf - /path/to/backup/dir | ssh remotehost "cat - > backupfile.tar"

เรากำลังสร้าง tarball และเขียนถึงSTDOUTสิ่งปกติ เนื่องจากเรากำลังใช้ SSH เพื่อรันคำสั่งระยะไกล STDIN ได้รับการแมปไปของSTDIN catซึ่งเราก็เปลี่ยนเส้นทางไปยังไฟล์


11
นั่นไม่ใช่การเรียงลำดับของ "การเปลี่ยนเส้นทางอินพุต / เอาท์พุตแฟนซี" - เป็นเรื่องธรรมดาที่น่าเบื่อ ssh อ่านจาก STDIN เช่นเดียวกับเครื่องมืออื่น ๆ และส่งผ่านไปยังกระบวนการระยะไกล :)
Daniel Pittman

7
@DanielPittman: แต่มันสนุกมากขึ้นที่จะเรียกมันว่า
Scott Pack

7
ในทำนองเดียวกันnetcatที่ปลายทั้งสองทำให้ช่องทางการสื่อสารที่เรียบง่ายและดีเยี่ยม tar cf - /path/to/dir | nc 1.2.3.4 5000บนเซิร์ฟเวอร์หนึ่งnc -l -p 5000 > backupfile.tarในที่อื่น ๆ
MikeyB

1
@ MikeyB: จุดดี Netcat เป็นโปรโตคอลข้อความที่ชัดเจนดังนั้นระวังข้อมูลที่ละเอียดอ่อน ฉันมักจะใช้ netcat สำหรับสิ่งที่เฉพาะเจาะจงมากขึ้นเช่นการซื้อไดรฟ์เครือข่าย (ala dd) ผ่านเครือข่ายท้องถิ่นและการสแกนพอร์ต
Scott Pack

2
@MikeyB: คุณเป็นคนที่ชอบบินและที่นั่งกางเกงของคุณ!
Scott Pack

28

วิธีที่สะดวกในการไพพ์ข้อมูลระหว่างโฮสต์เมื่อคุณไม่จำเป็นต้องกังวลเกี่ยวกับความปลอดภัยของลวดที่ใช้netcatทั้งสองด้านของการเชื่อมต่อ

สิ่งนี้ยังช่วยให้คุณตั้งค่าแบบอะซิงโครนัส:

ใน "ผู้รับ" (จริงๆแล้วคุณจะมีการสื่อสารสองทาง แต่ง่ายกว่าที่จะคิดแบบนี้) เรียกใช้:

nc -l -p 5000 > /path/to/backupfile.tar

และใน "ผู้ส่ง" ให้เรียกใช้:

tar cf - /path/to/dir | nc 1.2.3.4 5000

ดีมากที่จะรู้ นี่เป็นสิ่งที่ดีถ้าการเชื่อมต่อทางกายภาพเชื่อถือได้เช่นบางทีอาจเป็นเครือข่ายสำรองหรือถ้าการเชื่อมต่อนั้นถูกอุโมงค์อยู่แล้ว
Wesley

หรือถ้าข้อมูลเป็นสิ่งที่สาธารณะอยู่แล้ว
ซามูเอลเอ็ดวินวอร์ด

1
+1 netcat เป็นเครื่องมือที่ทรงคุณค่าโดยเฉพาะอย่างยิ่งเมื่อคุณไม่ได้ใช้งานเซิร์ฟเวอร์ ssh
kwarrick

21

เครื่องมือที่มีประสิทธิภาพมากสำหรับการสร้างการเชื่อมต่อหนึ่ง - socatและแบบสองทิศทางคือ เพื่อให้ดูสั้นที่เป็นไปได้ดูตัวอย่างของmanpage

มันแทนที่netcatและเครื่องมือที่คล้ายกันอย่างสมบูรณ์และมีการสนับสนุนการเชื่อมต่อที่เข้ารหัส SSL สำหรับผู้เริ่มต้นอาจไม่ง่ายพอ แต่อย่างน้อยก็รู้ดีว่ามันมีอยู่จริง


1
@WesleyDavid: สำหรับ "Update" ของคุณ: เพื่อความสมบูรณ์ฉันได้เพิ่มคำตอบของฉันแล้วว่า socat มีการรองรับ SSL ดังนั้นการเข้ารหัสจึงเป็นไปได้ด้วย socat เช่นกัน อย่างไรก็ตามในกรณีส่วนใหญ่ ssh เป็นวิธีที่ดีกว่าและง่ายกว่าดังนั้นฉันจะเลือกคำตอบของ ScottPack ด้วย
jofel

5

TL; DR

สิ่งต่าง ๆ มีความซับซ้อนขึ้นเล็กน้อยเมื่อคุณมีเซิร์ฟเวอร์ป้อมปราการที่ต้องใช้งาน

  1. คุณสามารถส่งผ่านsshคำสั่งที่sshชอบ:

    • cat local_script.sh | ssh -A usera@bastion ssh -A userb@privateserver "cat > remote_copy_of_local_script.sh; bash remote_copy_of_local_script.sh"
  2. ระวังเทอร์มินัลหลอก


โปรดทราบว่าจุดสำคัญที่สำคัญที่นี่คือsshเช่นเดียวกับเครื่องมือส่วนใหญ่เพียงปฏิบัติstdoutและstdinแก้ไขตามค่าเริ่มต้น

อย่างไรก็ตามเมื่อคุณเริ่มที่จะเห็นตัวเลือกที่ชอบDisable pseudo-terminal allocation.และForce pseudo-terminal allocation.คุณอาจต้องทำการทดลองและข้อผิดพลาดเล็กน้อย แต่ตามกฎทั่วไปคุณไม่ต้องการเปลี่ยนttyพฤติกรรมยกเว้นว่าคุณกำลังพยายามแก้ไขขยะที่อ่านไม่ออก / ไบนารีในเครื่องจำลองเทอร์มินัล

ตัวอย่างเช่นฉันมักจะใช้-Atเพื่อให้ ssh-agent ของเวิร์กสเตชันของฉันได้รับการส่งต่อและเพื่อให้การเรียกใช้ tmux จากระยะไกลไม่ได้ barf binary (เช่นนั้นssh -At bastion.internal tmux -L bruno attach) และสำหรับนักเทียบท่าด้วยเช่นsudo docker exec -it jenkins bashกัน

อย่างไรก็ตาม-tค่าสถานะสองค่านี้ทำให้ยากต่อการติดตามความเสียหายของข้อมูลเมื่อฉันพยายามทำสิ่งนี้:

# copy /etc/init from jenkins to /tmp/init in testjenkins running as a container
ssh -A bastion.internal \
ssh -A jenkins.internal \
sudo tar cf - -C /etc init | \
sudo docker exec -i testjenkins \
bash -c 'tar xvf - -C /tmp'

# note trailing slashes to make this oneliner more readable.

2

ลองใส่กุญแจสาธารณะ ssh ของคุณในโฮสต์อื่นเพียงแค่คำสั่งเดียว

ssh root@example.com 'cat >> .ssh/authorized_keys' < .ssh/id_rsa.pub

2

ฉันคิดว่านี่เป็นวิธีที่ง่ายที่สุดหลังจากตั้งค่าไม่มีการจับรหัสผ่านระหว่างเซิร์ฟเวอร์สำหรับผู้ใช้ที่คุณใช้คำสั่งดังนี้:

ยังไม่ย่อ

tar cf - . | ssh servername "cd /path-to-dir && tar xf -"

บีบอัดได้ทันที

tar czf - . | ssh servername "cd /path-to-dir && tar xzf -"

การใช้การบีบอัดไฟล์ tar เป็นความคิดที่แย่มากหากคุณsshได้รับการกำหนดค่าสำหรับการบีบอัดแล้ว
Anthon

@ อันนี้ทำไมถึงแย่ขนาดนั้นและจะมีวิธีการตรวจสอบว่าการบีบอัด ssh ถูกเปิดใช้งานแล้ว?
Tom Hale

1
@TomHale ขึ้นอยู่กับความเร็วของระบบของคุณสิ่งนี้อาจทำให้การดำเนินงานโดยรวมช้าลงเนื่องจากการบีบอัดข้อมูลครั้งที่สองใช้เวลา แต่ไม่น่าจะเป็นการเพิ่มจำนวนไบต์ Compressionสามารถตั้งค่าในไฟล์ config ใด ๆ ก็ได้การตรวจสอบอย่างรวดเร็วสำหรับสิ่งนั้นคือการดูว่าssh -v localhost exit 2>&1 | fgrep -i compressให้เอาต์พุตใด ๆ หรือไม่ (AFAIK ไม่มีตัวเลือกในการดัมพ์การกำหนดค่าตามที่ ssh อ่านแล้ว)
Anthon

tarมี-C pathแฟล็กที่ใช้งานได้ทั้งcและxคำสั่ง คุณไม่จำเป็นต้องใส่cdคำสั่งแยกต่างหากในนั้น (แต่เป็นการดีที่จะทราบว่าคุณสามารถเรียกใช้มากกว่าหนึ่งคำสั่ง)
Bruno Bronosky

@Bruno -Cเป็นส่วนขยายของ GNU (แต่ตอนนี้รองรับโดย bsdtar และ schily tar)
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.