स्टड के माध्यम से कई फ़ाइलों को पास करना (ssh पर)


15

मेरे पास एक दूरस्थ मेजबान पर एक कार्यक्रम है, जिसके निष्पादन को मुझे स्वचालित करने की आवश्यकता है। कमांड उस प्रोग्राम को निष्पादित करता है, उसी मशीन पर, कुछ इस तरह दिखता है:

/path/to/program -a file1.txt -b file2.txt

इस मामले में, file1.txtऔर file2.txtकार्यक्रम के भीतर पूरी तरह से अलग चीजों के लिए उपयोग किया जाता है, इसलिए मैं catउन्हें बस एक साथ नहीं कर सकता । हालाँकि, मेरे मामले में, file1.txtऔर file2.txtयह कि मैं कार्यक्रम में पास होना चाहता हूँ केवल मेरे डिवाइस पर मौजूद है, न कि उस होस्ट पर जहाँ मुझे प्रोग्राम को निष्पादित करने की आवश्यकता है। मुझे पता है कि मैं एसएसएच के माध्यम से कम से कम एक फाइल को इसके माध्यम से पारित कर सकता हूं stdin:

cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt

लेकिन, चूंकि मुझे होस्ट पर फ़ाइलों को संग्रहीत करने की अनुमति नहीं है, इसलिए मुझे file2.txtवहां पर भी एक रास्ता चाहिए । मुझे लगता है कि यह पर्यावरण चर और के रचनात्मक उपयोग के दुरुपयोग के माध्यम से संभव हो सकता हैcatsed साथ और एक साथ , लेकिन मुझे यह समझने के लिए कि मैं उनका उपयोग कैसे करूँगा, यह समझने के लिए पर्याप्त उपकरण नहीं जानता। यह करने योग्य है, और कैसे?


2
catऔर sedयहाँ समाधान नहीं हैं।
स्लीक्स

संभवत: मैं माउंट करने में सक्षम हो सकता हूं, लेकिन प्रॉक्सी और सुरक्षा बाधाओं को देखते हुए मुझे यकीन नहीं है कि मैं इसके साथ दूर जा पाऊंगा।
ग्रीन क्लोक गाइ

क्या आपके पास ssh फ़ोल्डर को माउंट करने के लिए रिमोट मशीन में अनुमति है?
15

1
यदि आप दूरस्थ मशीन से अपने स्थानीय एक के लिए एक ssh सत्र खोल सकते हैं, तो SSH फ़ोल्डर को माउंट करने के लिए नेटवर्क स्तर पर कोई समस्या नहीं है।
स्लीक्स

क्या आप फॉरवर्डिंग कर सकते हैं? आपके पास स्थानीय और दूरस्थ छोर पर क्या सिस्टम और शेल हैं?
मस्जिद

जवाबों:


18

यदि आपके प्रोग्राम में तर्क के रूप में दी गई फाइलें टेक्स्ट फाइलें हैं, और आप उनकी सामग्री को नियंत्रित करने में सक्षम हैं (आप एक पंक्ति जानते हैं जो उनके अंदर नहीं होती है), तो आप यहां कई-दस्तावेजों का उपयोग कर सकते हैं:

{
    echo "cat /dev/fd/3 3<<'EOT' /dev/fd/4 4<<'EOT' /dev/fd/5 5<<'EOT'"
    cat file1
    echo EOT
    cat file2
    echo EOT
    cat file3
    echo EOT
} | ssh user@host sh

यहाँ catएक नमूना आदेश दिया गया है जो तर्कों के रूप में फ़ाइल नाम लेता है। इसके बजाय यह हो सकता है:

echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'

प्रत्येक EOTफ़ाइल को क्रमशः फ़ाइलों में से प्रत्येक में न बदलें ।


1
यह दृष्टिकोण काफी चतुर है! यदि फ़ाइलें पाठ नहीं हैं, तो आप उन्हें बेस 64 या यहाँ तक कि अच्छे ol 'uuencode ... जैसी किसी चीज़ के साथ इनकोड / डिकोड कर सकते हैं ... बहुत अच्छा!
फिल्मब्रांडेन

3
ध्यान दें कि कई (अधिकांश) शट कार्यान्वयन अस्थायी फ़ाइलों का उपयोग करके यहां दस्तावेजों को लागू करते हैं, इसलिए यह ओपी के लिए काम नहीं कर सकता है यदि उन्हें दूरस्थ होस्ट पर फ़ाइलों को संग्रहीत करने की अनुमति नहीं है।
स्टीफन चेज़लस

2
dash( /bin/shडेबियन, ubuntu, आदि में), busybox sh, /bin/shFreeBSD से और yashअस्थायी फ़ाइलों को यहाँ-दस्तावेज़ों के लिए उपयोग नहीं करते। मैंने वास्तव में इसे केवल-पढ़ने के लिए चुरोट के साथ परीक्षण किया है। बेशक, /dev/fd/फ़ाइलें उपलब्ध होनी चाहिए - एक स्टॉक फ्रीबीएसडी सिस्टम पर ही /dev/fd/0-2हैं, इसलिए fdescfsइसे चालू करना होगा /dev/fd
मॉसवी

1
मैं ASCII सूचना विभाजकों का प्रशंसक हूं , जिन्हें बिना किसी बाधा के खेतों को परिसीमित करने के लिए डिज़ाइन किया गया है। U+001C"सूचना विभाजक चार" (फ़ाइल विभाजक, एफएस) है और इस मामले के लिए आदर्श है, हालांकि बाइनरी फाइलें संयोग से इसका उपयोग कर सकती हैं। इसलिए, मैं EOT="$(printf $'\x1c')"उन्नत गोले या EOT="$(awk 'BEGIN{printf"%c",28}')"संगतता के लिए सुझाव देना चाहूंगा । जब आप इसे लगाते हैं, तो आपको इसे उद्धृत करने की आवश्यकता होगी, जैसे कि echo "$EOT$EOT$EOT"(एक बाइनरी फ़ाइल के मिलान की बाधाओं को कम करने के लिए तिगुना)।
एडम काट्ज

यदि आप tty का उपयोग करने जा रहे हैं तो ttyकमांड का उपयोग क्यों नहीं करते हैं ? जब तक मैं कुछ याद नहीं कर रहा हूँ - जो मुझे लगता है कि संभव है?
15-11 बजे प्रीफटन

14

शायद वही नहीं जो आप चाहते हैं ... लेकिन शायद ssh द्वारा खोले गए पाइप के माध्यम से तारबॉल भेजने पर विचार करें?

आपने कहा था कि:

मुझे होस्ट पर फ़ाइलों को संग्रहीत करने की अनुमति नहीं है।

यह संभव है कि आपके पास लंबे समय तक फ़ाइलों को संग्रहीत करने के लिए एक लिखने योग्य घर निर्देशिका या अन्य सुविधाजनक स्थान नहीं है, लेकिन मैं कहूंगा कि यह संभावना नहीं है कि आपके पास कोई भी योग्य स्थान नहीं है, भले ही एक अस्थायी हो tmpfs जो केवल आपके लिए उपलब्ध हो। विशेष संबंध।

कई कार्यक्रमों (और यहां तक ​​कि libc routines) को एक लिखने योग्य की आवश्यकता होती है /tmp, इसलिए यह बहुत संभव है कि एक आपके लिए उपलब्ध होगा।

तब आप एक स्क्रिप्ट का उपयोग कर सकते हैं जो टारबॉल को एक अस्थायी निर्देशिका में अनपैक करेगा, अपने प्रोग्राम को चलाएगा और ssh कनेक्शन के माध्यम से सफाई करेगा।

कुछ इस तरह:

$ tar cf - file1.txt file2.txt |
  ssh host.name '
      set -e
      tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
      cleanup () { rm -rf "$tmpdir"; }
      trap cleanup EXIT
      cd "$tmpdir"
      tar xf -
      /path/to/program -a file1.txt -b file2.txt
  '

यह फ़ाइल पथों के साथ कुछ अतिरिक्त देखभाल की आवश्यकता हो सकती है और विचार करने के लिए कुछ कोने के मामले हैं (उनके लिए परीक्षण), लेकिन सामान्य दृष्टिकोण काम करना चाहिए।

यदि कोई लेखन योग्य निर्देशिका उपलब्ध नहीं है, तो एक संभावित दृष्टिकोण programएकल इनपुट के रूप में टारबॉल को संशोधित करने और इसकी सामग्री को मेमोरी में अनपैक करने के लिए होगा। उदाहरण के लिए, यदि programपायथन स्क्रिप्ट है, तो अंतर्निहित tarfileमॉड्यूल का उपयोग करके आसानी से ऐसा कुछ पूरा किया जाएगा।


3
यहां तक ​​कि इसे टारबॉलिंग की परेशानी से गुजरे बिना - मैंने कम से कम एक फाइल को /tmp/सीधे लिखने और उसका उपयोग करने का फैसला किया है।
ग्रीन क्लोक गाइ

2
टारबॉल दृष्टिकोण के कुछ फायदे हैं, जैसा कि आप एकल ssh कनेक्शन का उपयोग करते हैं (सफलता / असफलता के लिए परीक्षण करने की आवश्यकता नहीं है) और कई समवर्ती रन एक दूसरे में चलने की संभावना नहीं है (अलग-अलग रनों के लिए / tmp में फ़ाइलों का उपयोग करें और हटाएं) ।) लेकिन मुझे लगता है कि ssh से आपको सबसे अच्छा मिलेगा क्योंकि यह अभी मौजूद है। सौभाग्य!
filbranden

3
@GreenCloakGuy तो सब के बाद, आप फ़ाइलों को सर्वर पर ठीक स्टोर कर सकते हैं। कृपया तदनुसार प्रश्न को संशोधित करें।
मच्छी

1
@mosvy कर सकते हैं , हाँ, लेकिन नहीं करना चाहते । सवाल खड़ा है, "किसी भी फाइल को संग्रहीत किए बिना ऐसा करना संभव है", जिसका उत्तर "शायद, लेकिन मेरे मामले में नहीं" प्रतीत होता है
ग्रीन क्लोक गाइ

5

यदि आप एक टीसीपी श्रोता (एक उच्च बंदरगाह हो सकता है) सेट कर सकते हैं, तो आप दूसरे इनपुट सुविधाओं को स्थापित करने के लिए एक दूसरे एसएसएच सत्र का उपयोग कर सकते हैं nc

उदाहरण:

सर्वर पर यह स्क्रिप्ट है ( ~/script.bash):

#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'

और ये दोनों फाइलें स्थानीय स्तर पर हैं:

$ cat a 
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb

अब पहले दूसरा स्रोत शुरू करें ( $servसर्वर है):

ssh "$serv" nc -l -p 2222 -q1 <b &

और कमांड को उचित तरीके से चलाएं:

$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+  Done                    ssh "$serv" nc -l -p 2222 -q1 < b

2

यह एक टिप्पणी में स्थापित किया गया था जो कि /tmpलिखने योग्य है, इसलिए पहले से एक फाइल पर कॉपी करें:

scp -p file2.txt host.name:/tmp/
ssh host.name "/path/to/program -a /dev/stdin -b /tmp/file2.txt && rm /tmp/file2.txt" < file1.txt

यह भी की नकल की फ़ाइल के बाद एक सफल रन (बदलने को साफ &&एक करने के लिए ;आप सफलता की परवाह किए बिना इसे हटाने के लिए चाहते हैं, लेकिन फिर ध्यान दें कि आप बाहर निकलने के मूल्य खो देंगे)।


अगर यह स्वीकार्य नहीं है, तो मैं इसके लिए /path/to/programया एक आवरण के साथ छेड़छाड़ का प्रस्ताव रखूंगा जो दो फाइलों को एक एकल इनपुट स्ट्रीम से अलग कर सकता है जैसे:

awk 'FNR == 1 && NR > 1 { printf "%c%c%c", 28, 28, 28 } 1' file1.txt file2.txt \
  | ssh host.name /path/to/tweaked_program

यह ASCII सूचना विभाजक चार (फ़ाइल विभाजक, एफएस) का उपयोग करता है और इसे तीन गुना किया गया है ताकि हम एक बाइनरी फ़ाइल संयोगवश उस स्ट्रिंग वाले संयोग को कम कर सकें। तुम्हारीtweaked_program तब विभाजक को दिए गए इनपुट को विभाजित करेगा और फिर चर के रूप में दो सहेजे गए फ़ाइलों पर काम करेगा।

बेशक, यदि आप एक ऐसी भाषा का उपयोग कर रहे हैं जिसमें टारबॉल से निपटने के लिए पुस्तकालय हैं, तो एक सुरक्षित और क्लीनर दृष्टिकोण बस tarइस तरह के कोड में पाइप करने के लिए sshहोगा:

tar -zpc file1.txt file2.txt |ssh host.name /path/to/tweaked_program

और आपका tweaked_programडिकम्प्रेस होगा और आर्काइव को खोलेगा, प्रत्येक फाइल को एक अलग वेरिएबल में सेव करेगा, और फिर programवेरिएबल पर ओरिजिनल लॉजिक रन करेगा ।


1

यदि आपको बंदरगाहों को अग्रेषित करने की अनुमति है ssh, और आपके पास wgetदूरस्थ मशीन और busyboxस्थानीय मशीन पर पहुंच है , तो आप कुछ ऐसा कर सकते हैं:

mkdir /tmp/test; cd /tmp/test
echo 1st_file > 1st_file
echo 2nd_file > 2nd_file

busybox httpd -f -p 127.0.0.1:11080 &
ssh USER@HOST -R 10080:127.0.0.1:11080 '
        cat <(wget -q -O- http://localhost:10080/1st_file) \
            <(wget -q -O- http://localhost:10080/2nd_file)
'
kill $!

(का उपयोग करते हुए cat एक उदाहरण कार्यक्रम के रूप में जो दो फ़ाइल तर्क लेता है)।

केवल बंदरगाहों को अग्रेषित करने की क्षमता -Rआवश्यक है - http करने के बजाय, आप अन्य विधियों का उपयोग कर सकते हैं, जैसे। यदि आपका netcatसमर्थन -dऔर -Nविकल्प:

nc -Nl localhost 11001 < 1st_file &
nc -Nl localhost 11002 < 2nd_file &
ssh USER@HOST -R 10001:localhost:11001 -R 10002:localhost:11002 '
        cat <(nc -d localhost 10001) <(nc -d localhost 10002)

को प्रतिस्थापित करने के तरीके हो सकते हैं <(...)प्रक्रिया प्रतिस्थापन यदि दूरस्थ मशीन पर लॉगिन शेल ksh- या bash- जैसे नहीं है।

कुल मिलाकर, यह बहुत अच्छा नहीं है - सटीक प्रणाली / गोले / विन्यास / अनुमतियाँ (जो आपने प्रदान नहीं की है) के बारे में बेहतर ज्ञान होशियार समाधानों की अनुमति दे सकता है।


-1

अद्यतन: यह वास्तव में काम नहीं करता है, ssh को एक बहुत ही निर्धारित विचार है कि stdin और stdout / stderr का क्या मतलब है और वास्तव में इसे से पढ़ने के लिए stderr की अनुमति नहीं देता है। मैं कुछ दिनों में इस उत्तर को हटा दूंगा क्योंकि यह काम नहीं करता है। बहुत ही रोचक चर्चा के लिए धन्यवाद !!!


दुर्भाग्य से यह सीधे करने के लिए, के बाद से एक शानदार तरीका नहीं है sshग्राहक केवल तीन फ़ाइल वर्णनकर्ता (पारित करेंगे stdin, stdoutऔरstderr सर्वर के लिए) है और यह अतिरिक्त फ़ाइल वर्णनकर्ता (जो इस विशेष उपयोग के मामले के लिए मददगार होगा पारित करने के लिए प्रावधानों नहीं है ।)

(यह भी ध्यान दें कि SSH प्रोटोकॉल में अतिरिक्त फाइल डिस्क्रिप्टर पास करने के प्रावधान हैं, केवल sshक्लाइंट उस सुविधा का उपयोग करने का एक तरीका लागू नहीं करता है। सैद्धांतिक रूप से, क्लाइंट को पैच के साथ विस्तारित करना इस सुविधा को उजागर करने के लिए पर्याप्त होगा।)

आप जिस चीज़ की तलाश कर रहे हैं उसे पूरा करने के लिए एक हैक करने का तरीका stderrदूसरा फाइल पास करने के लिए फ़ाइल डिस्क्रिप्टर 2 ( फ़ाइल डिस्क्रिप्टर) का उपयोग करना है। कुछ इस तरह:

$ ssh remote.name \
      /path/to/program -a /dev/stdin -b /dev/stderr \
      <file1.txt 2<file2.txt

यह काम करना चाहिए, यह सिर्फ एक मुद्दे का कारण बन सकता है अगर programस्टडर को लिखने की कोशिश करता है। आप प्रोग्राम चलाने से पहले दूरस्थ छोर पर फ़ाइल डिस्क्रिप्टर को फिर से जोड़कर उसके चारों ओर काम कर सकते हैं। आप file2.txtफाइल डिस्क्रिप्टर 3 में स्थानांतरित कर सकते हैं और स्टैडआउट को मिरर करने के लिए फिर से ओपन करें:

$ ssh remote.name \
      /path/to/program -a /dev/stdin -b /dev/fd/3 \
      '3<&2' '2>&1' \
      <file1.txt 2<file2.txt

मैंने वास्तव में इसका परीक्षण नहीं किया है (फोन पर टाइप करना) लेकिन कम से कम सिद्धांत में मैं यह काम करने की उम्मीद करूंगा। मुझे पता है अगर किसी कारण के लिए यह नहीं करता है। चीयर्स!
फाइलब्रांडेन

यह बिल्कुल काम नहीं करेगा। हैक किए गए ssh के साथ भी नहीं। AFAIK stderr एक अलग चैनल का उपयोग नहीं करता है, लेकिन कुछ विशेष प्रकार का संदेश। लेकिन हाँ, ssh चैनल को पाइप या अनाम यूनिक्स डोमेन सॉकेट के रूप में एक्सेस करने में सक्षम होने (इसके बजाय सॉकेट फॉरवर्डिंग करने के लिए) बहुत अच्छा होगा, यह किसी भी प्रकार या आकार में संभव नहीं लगता है।
मस्जिद

@mosvy, fd 0, 1 और 2 रिमोट कमांड पर 3 अलग-अलग पाइप होंगे। डेटा ssh कनेक्शन में 3 अलग-अलग चैनलों के माध्यम से यात्रा करता है, लेकिन वे यूनि-दिशात्मक हैं (क्लाइंट से fd 0 के लिए और सर्वर से क्लाइंट के लिए 1 और 2 के लिए), इसलिए सिस्टम पर भी जहां पाइप द्विदिश हैं, जिसने जीता ' t काम। लिनक्स पर, रीडायनली मोड में ओपनिंग / डेव / स्टैडर पाइप के दूसरे छोर पर देता है, इसलिए यह कभी भी काम नहीं करेगा।
स्टीफन चेजलस

ध्यान दें कि अंतिम एक उपयोगकर्ता के लॉगिन शेल को दूरस्थ रूप से मानता है। नाम बॉर्न-लाइक है ( 3<&2एक बॉर्न शेल ऑपरेटर है, और sshd क्लाइंट द्वारा भेजे गए कमांड की व्याख्या करने के लिए उपयोगकर्ता के लॉगिन शेल को चलाता है)
स्टीफन चासनास

2
@ StéphaneChazelas नहींं, एक एकल ssh चैनल को stdin / stdout / stderr के लिए उपयोग किया जाता है, और stderr डेटा को SSH_MSG_CHANNEL_EXTENDED_DATAसेट किए गए प्रकार के साथ संदेशों के माध्यम से स्थानांतरित किया जाता है SSH_EXTENDED_DATA_STDERR। आप पूरी बात यहां
मसलन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.