ปัญหาเกี่ยวกับคำตอบจาก @jakuje คือ: ใช้งานได้กับซ็อกเก็ตเท่านั้น แต่คุณไม่สามารถใช้เครื่องมือ UNIX มาตรฐานที่คาดหวังไฟล์ได้
ssh -R/tmp/sock.remote:/tmp/sock.local "$HOST" 'LANG=C cat >/tmp/sock.remote'
bash: /tmp/sock.remote: ไม่มีอุปกรณ์หรือที่อยู่ดังกล่าว
ยังมีปัญหาที่ไฟล์ซ็อกเก็ตท้องถิ่นไม่ได้ถูกลบบนโฮสต์ระยะไกล; เมื่อถัดไปที่คุณเรียกใช้คำสั่งเดียวกันคุณจะได้รับคำเตือนและซ็อกเก็ตจะไม่ถูกสร้างขึ้นใหม่อย่างถูกต้อง คุณสามารถให้ตัวเลือก-o StreamLocalBindUnlink=yes
เพื่อssh
ยกเลิกการเชื่อมโยงซ็อกเก็ตเก่านั้น แต่ในการทดสอบของฉันมันไม่เพียงพอ คุณต้องแก้ไขsshd_config
ให้มีStreamLocalBindUnlink=yes
เพื่อให้ตัวเลือกนั้นใช้งานได้
แต่คุณสามารถใช้socat
หรือnetcat
หรือเครื่องมือที่คล้ายกันอื่น ๆ ที่สนับสนุนระบบปฏิบัติการยูนิกซ์ซ็อกเก็ตท้องถิ่น ( netcat-traditional
คือไม่พอ!) เพื่อใช้ส่งต่อซ็อกเก็ตในท้องถิ่นสำหรับการถ่ายโอนไฟล์:
# start local process listening on local socket, which receives the data when ssh opens the connections and saves it to a local file
nc -l -N -U /tmp/sock.local >/tmp/file.local &
# connect to remote $HOST and pipe the remote file into the remote socket end
ssh \
-o ExitOnForwardFailure=yes \
-o StreamLocalBindUnlink=yes \
-R /tmp/sock.remote:/tmp/sock.local \
"$HOST" \
'nc -N -U /tmp/sock.remote </tmp/file.remote'
คุณยังสามารถเรียกใช้คำสั่งแบบโต้ตอบซึ่งในกรณีนี้คุณควรใช้ssh -t
เพื่อจัดสรร TTY
ปัญหาเกี่ยวกับวิธีแก้ปัญหานี้คือคุณต้องเขียนโค้ดพา ธ ของซ็อกเก็ต UNIX แบบโลคอล: ในพื้นที่นี่ไม่ใช่ปัญหามากเท่าที่คุณสามารถรวม$$
ไว้ในพา ธ เพื่อทำให้เป็นเอกลักษณ์เฉพาะต่อกระบวนการหรือผู้ใช้เป็นไดเรกทอรีชั่วคราว รีโมตเอนด์คุณควรอย่าใช้ไดเร็กตอรี่ที่เขียนได้ทั่วโลก/tmp/
อย่างที่ฉันทำในตัวอย่าง ไดเรกทอรีจะต้องมีอยู่แล้วเมื่อssh
เริ่มเซสชัน และซ็อกเก็ตไอโหนดจะยังคงอยู่แม้หลังจากปิดเซสชันดังนั้นการใช้บางอย่างเช่น "$ HOME / .ssh. $$" จะทำให้ไดเรกทอรีของคุณยุ่งเหยิงด้วยไอโหนดที่ตายแล้วในช่วงเวลานั้น
คุณยังสามารถใช้ซ็อกเก็ต TCP ที่เชื่อมโยงกับlocalhost
ซึ่งจะช่วยให้คุณประหยัดจากความยุ่งเหยิงในระบบไฟล์ของคุณด้วย inodes ที่ตายแล้ว แต่ถึงกระนั้นคุณก็ยังมีปัญหาในการเลือกหมายเลขพอร์ตที่ไม่ได้ใช้ ดังนั้นจึงยังไม่เหมาะ ( ssh
มีรหัสในการจัดสรรพอร์ตแบบไดนามิก แต่ฉันไม่พบวิธีการดึงข้อมูลนั้นบนรีโมตโฮสต์)
อาจเป็นวิธีที่ง่ายที่สุดในการคัดลอกไฟล์คือการใช้ฟังก์ชั่นการแบ่งปันการเชื่อมต่อในตัวของ ssh และเพื่อทำscp
หรือsfrp
คำสั่งในขณะที่เซสชันการโต้ตอบของคุณยังคงทำงานแบบขนาน ดูการคัดลอกไฟล์กลับไปที่ระบบท้องถิ่นที่มี SSH
closefrom(STDERR_FILENO + 1)
สายต่าง ๆภายใต้รหัสที่มา OpenSSH คุณพยายามทำอะไรที่ต้องการสิ่งนี้