SSH: स्टड, स्टडआउट, स्टेडर के अलावा अतिरिक्त "पाइप" एफडी प्रदान करें


12

जब SSH के साथ एक होस्ट से कनेक्ट करते हैं, आमतौर पर तीन "पाइप" होस्ट और अतिथि के बीच प्रदान की जाती हैं, के लिए stdin, stdout, और stderr

क्या अतिरिक्त फ़ाइल डिस्क्रिप्टर ( 3और आगे) के लिए फॉरवर्ड बनाने के लिए कमांड-लाइन विकल्प है ?

उदाहरण के लिए, मैं करना चाहूंगा

ssh --forwardfd=10:3 remotehost 'echo test >&3'

जो 'परीक्षण' को स्थानीय रूप से खोले गए फ़ाइल डिस्क्रिप्टर 10 में प्रिंट करेगा।


2
शायद ट्रिकी स्रोत संपादन के बिना नहीं, closefrom(STDERR_FILENO + 1)ओपनएसएसएच स्रोत कोड के तहत विभिन्न कॉल दिए गए हैं । आप ऐसा करने की कोशिश कर रहे हैं जो यह मांग करता है।
17

प्रोटोकॉल stdin/ out/ के अलावा अतिरिक्त स्ट्रीम को टनलिंग का समर्थन करता है err, लेकिन AFAIK, कोई भी सर्वर / क्लाइंट किसी भी तरह से उस सुविधा का समर्थन नहीं करता है।
सलवा

@ ऑथर नॉट ओपी, और यह एक लंबा समय हो गया है, लेकिन अगर आप अभी भी उत्सुक हैं कि यह किस लिए उपयोगी हो सकता है, तो मैं यहाँ क्या खोजने के लिए उम्मीद कर रहा था कि कैसे ssh के माध्यम से पाइप किया जाए, बैश की स्क्रिप्ट और सही उस स्क्रिप्ट के लिए स्टडिन। कुछ infinite-output-cmd | ssh user@host bash /proc/self/fd/3 3< local-script-to-execute-remotely.sh
हद

@ यह मेरे लिए होता है कि जैसे कुछ की --forwardfdजरूरत भी नहीं होनी चाहिए। sshकिसी भी अन्य चीज़ को खोलने से पहले ओपन फाइल डिस्क्रिप्टर क्या हैं, इसकी जांच कर सकते हैं, और उन्हें रिमोट साइड पर एक ही फाइल डिस्क्रिप्टर पर स्वचालित रूप से अग्रेषित कर सकते हैं। यह मेरे उदाहरण की तरह पूरी तरह पारदर्शी हो सकता है। मुझे आश्चर्य है कि उसके लिए पैच करना कितना मुश्किल होगा ssh। जैसा आपने कहा, उन कारणों के आधार पर यह मुश्किल हो सकता है closefrom(STDERR_FILENO + 1)
जोएल सेप

जवाबों:


6

आप सॉकेट फ़ॉरवर्डिंग का उपयोग करके ऐसा कर सकते हैं, जो ओपनश-6.7 के बाद से उपलब्ध है। यह किसी प्रकार का पाइप है। इस तकनीक को यहाँ उदाहरण के लिए वर्णित किया गया है: http://www.25thandclement.com/~william/projects/streamlocal.html

आप अपने डेटा के लिए दो-दिशा मार्ग प्राप्त करेंगे। Mysql के साथ उदाहरण है:

अपने स्थानीय उदाहरण में दूरस्थ सर्वर पर प्रॉक्सी MySQL क्लाइंट कनेक्शन:

ssh -R/var/run/mysql.sock:/var/run/mysql.sock \
    -R127.0.0.1:3306:/var/run/mysql.sock somehost 

1

मुझे यकीन है कि यह संभव होना चाहिए। मैं केवल एक हैक का सुझाव दे सकता हूं जहां आप प्रत्येक फ़ाइल विवरणक की एक जोड़ी को ले जाने के लिए अतिरिक्त ssh कनेक्शन का उपयोग करते हैं। उदाहरण के लिए, स्क्रिप्ट स्क्रिप्ट का निम्नलिखित प्रमाण स्थानीय डीडी 5 और 6 को दूरस्थ स्टडिन और स्टडआउट से जोड़ने के लिए डमी कमांड (स्लीप) चलाने के लिए पहले ssh करता है, इन fds को मानते हुए वे हैं जिन्हें आप सामान्य 0,1 में जोड़ना चाहते हैं। 2।

फिर असली ssh किया जाता है, और रिमोट पर यह रिमोट fds 5 और 6 को दूसरे ssh के स्टड और स्टडआउट से जोड़ता है।

एक उदाहरण के रूप में, यह स्क्रिप्ट रिमोट के माध्यम से एक gzipped man पेज को पारित करती है, जो कि unzips और इसे आदमी के माध्यम से चलाता है। असली ssh का स्टड और स्टडआउट अभी भी अन्य चीजों के लिए उपलब्ध है।

#!/bin/bash
exec 5</usr/share/man/man1/ssh.1.gz 6>/tmp/out6 # pretend need 5 and 6

ssh remote 'echo $$ >/tmp/pid; exec sleep 99999' <&5 >&6 &
sleep 1 # hack. need /tmp/pid to be set

ssh remote '
  pid=$(</tmp/pid) 
  exec 5</proc/$pid/fd/0 6>/proc/$pid/fd/1
  echo start
  gzip -d <&5 | man /dev/stdin >&6
  echo stop
  kill -hup $pid
'
wait
less /tmp/out6

1

@Jakuje से जवाब के साथ समस्या है: यह केवल के साथ काम करता सॉकेट , लेकिन आप नहीं कर सकते हैं उपयोगकर्ता मानक उम्मीद यूनिक्स उपकरण फ़ाइलें उन लोगों के साथ:

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करना होगा।

लेकिन आप फ़ाइल हस्तांतरण के लिए अग्रेषित स्थानीय सॉकेट का उपयोग करने के लिए UNIX लोकल सॉकेट ( यह पर्याप्त नहीं है!) का समर्थन करने वाले किसी अन्य समान उपकरण का उपयोग socatया कर सकते हैं :netcatnetcat-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 -tTTYs आवंटित करने के लिए उपयोग करना चाहिए ।

इस समाधान के साथ समस्या यह है कि आपको UNIX लोकल सॉकेट्स के रास्तों को हार्ड-कोड करना चाहिए: स्थानीय रूप से यह उतनी समस्या नहीं है जितना कि आप $$इसे अद्वितीय प्रक्रिया या उपयोगकर्ता को एक अस्थायी निर्देशिका बनाने के लिए पथ में शामिल कर सकते हैं , लेकिन दूरस्थ-अंत में आप विश्व-लेखन योग्य निर्देशिका का उपयोग नहीं करते हैं /tmp/जैसा कि मैं अपने उदाहरण में करता हूं। sshसत्र प्रारंभ होने पर निर्देशिका पहले से मौजूद होनी चाहिए । और सत्र बंद होने के बाद भी सॉकेट इनोड रहेगा, इसलिए "$ HOME / .ssh। $$" जैसी किसी चीज़ का उपयोग करने से समय के साथ आपकी निर्देशिका अव्यवस्थित हो जाएगी।

आप टीसीपी सॉकेट्स का उपयोग भी कर सकते हैं localhost, जो आपको अपने फाइल सिस्टम को मृत इनोड्स के साथ अव्यवस्थित करने से बचाएगा, लेकिन यहां तक ​​कि उनके साथ आपको अभी भी एक (अद्वितीय) अप्रयुक्त पोर्ट नंबर चुनने के लिए समस्या है। तो अभी भी आदर्श नहीं है। ( sshपोर्ट को गतिशील रूप से आवंटित करने के लिए कोड है, लेकिन मुझे दूरस्थ होस्ट पर उस जानकारी को पुनः प्राप्त करने का कोई तरीका नहीं मिला।)

शायद फ़ाइलों की प्रतिलिपि बनाने के लिए सबसे आसान समाधान का उपयोग करने ssh में निर्मित है कनेक्शन साझा करने कार्यक्षमता और एक करने के लिए scpया sfrp, जबकि अपनी इंटरैक्टिव सत्र अभी भी समानांतर में चल रहा है आदेश। फ़ाइल को ssh के साथ स्थानीय सिस्टम में वापस देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.