स्यूडो-टर्मिनल आवंटित नहीं किया जाएगा क्योंकि स्टडिन एक टर्मिनल नहीं है


345

मैं एक शेल स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो रिमोट सर्वर पर कुछ डायरेक्टरी बनाती है और फिर रिमोट पर मेरी लोकल मशीन से फाइल कॉपी करने के लिए scp का उपयोग करती है। यहाँ मेरे पास अभी तक क्या है:

ssh -t user@server<<EOT
DEP_ROOT='/home/matthewr/releases'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR=$DEP_ROOT"/"$datestamp
if [ ! -d "$DEP_ROOT" ]; then
    echo "creating the root directory"
    mkdir $DEP_ROOT
fi
mkdir $REL_DIR
exit
EOT

scp ./dir1 user@server:$REL_DIR
scp ./dir2 user@server:$REL_DIR

जब भी मैं इसे चलाता हूं मुझे यह संदेश मिलता है:

Pseudo-terminal will not be allocated because stdin is not a terminal.

और स्क्रिप्ट हमेशा के लिए लटक जाती है।

मेरी सार्वजनिक कुंजी सर्वर पर भरोसा की जाती है और मैं स्क्रिप्ट के बाहर सभी आदेशों को ठीक से चला सकता हूं। कोई विचार?


4
आप बस टर्मिनल का उपयोग करने के लिए निर्दिष्ट कर सकते हैं जैसेssh user@server /bin/bash <<EOT…
Buzut

3
@ बज़ट: आपका मतलब शेल है , लेकिन, हाँ, /bin/bashस्पष्ट रूप से निर्दिष्ट करना समस्या से बचने का एक तरीका है।
mklement0

1
@ mklement0 वास्तव में, यही मेरा मतलब है। Thx कि सुधार के लिए;)
बुज़ुत

जवाबों:


512

कोशिश करें ssh -t -t(या ssh -ttकम के लिए) छद्म tty आवंटन को मजबूर करने के लिए, भले ही स्टड एक टर्मिनल नहीं है।

इसे भी देखें: बैश स्क्रिप्ट द्वारा निष्पादित SSH सत्र को समाप्त करना

Ssh मैनपेज से:

-T      Disable pseudo-tty allocation.

-t      Force pseudo-tty allocation.  This can be used to execute arbitrary 
        screen-based programs on a remote machine, which can be very useful,
        e.g. when implementing menu services.  Multiple -t options force tty
        allocation, even if ssh has no local tty.

21
मैं एक स्क्रिप्ट में इसी तरह का मुद्दा रख रहा हूं जो यहां चलाया जाता है। मैंने -t जोड़ा, लेकिन अब मुझे एक नई त्रुटि मिल रही है। "tcgetattr: डिवाइस के लिए अनुपयुक्त ioctl"
MasterZ

5
क्यों ssh -t -tऔर क्या नहीं ssh -tt? क्या कोई अंतर है जिससे मैं अवगत नहीं हूं?
जैक

3
@MasterZ वही बात यहाँ। इसका उत्तर पाना अच्छा होगाInappropriate IOCtl for device
krb686

11
@ जैक -ttऔर -t -tसमकक्ष हैं; अलग से आर्गन्स निर्दिष्ट करना या एक साथ स्मोक्ड करना व्यक्तिगत शैली / पसंद का विषय बन जाता है, और जब यह नीचे आता है, तो इसे करने के लिए वैध तर्क होते हैं। लेकिन वास्तव में, यह सिर्फ व्यक्तिगत पसंद है।
जेडीएस

5
इसका क्या मतलब है जब यह कहता है "यहां तक ​​कि अगर ssh के पास कोई स्थानीय tty नहीं है"?
CMCDragonkai

192

इसके अलावा मैनुअल-T से विकल्प के साथ

छद्म tty आवंटन अक्षम करें


11
इस उत्तर को अधिक अंक चाहिए - इसका सही उत्तर, और ज़ैंको द्वारा उत्तर की तरह बहुत लंबा नहीं, इसका बेतुका जवाब है कि "ओह वैसे भी एक टीटीआई आवंटित करें -t के साथ -t" को 107 अंक मिलते हैं, जब आप इसे पूरी तरह से छोड़ सकते हैं
शून्य

2
सिर्फ उत्थान किया; इसने मेरे लिए -t
Vincent Hiribarren

15
'-t' काम करता है, हालांकि '-T' के साथ मुझे 'sudo: क्षमा करें, आपके पास sudo चलाने के लिए एक ट्टी होनी चाहिए'
इवान बालशोव

3
@ उत्तर: -ttविकल्प उन लोगों के लिए सर्वोत्तम है जो वास्तव में एक TTY चाहते हैं और ओपी की त्रुटि संदेश प्राप्त कर रहे हैं। -Tअगर आपको TTY की आवश्यकता नहीं है तो यह उत्तर बेहतर है।
एरचबस्चुल

3
@nhed - ज़रूर - लेकिन मुझे यकीन है कि मेरे जैसे अन्य लोगों को त्रुटि संदेश में त्रुटि Googling से यहाँ मिली है। यह स्पष्ट करना अनुचित नहीं है कि 2 प्रतिस्पर्धात्मक उत्तरों के बीच अन्य गुगलों को कैसे चुनना चाहिए। या शायद नहीं। मुझे नहीं पता
ErichBSchulz

91

प्रति zanco का जवाब है, तो आप के लिए एक दूरस्थ कमांड प्रदान नहीं कर रहे ssh, यह देखते हुए कि कैसे शेल कमांड लाइन पार्स करता है। इस समस्या को हल करने के लिए, अपने sshकमांड इनवोकेशन के सिंटैक्स को बदलें ताकि रिमोट कमांड सिंटैक्टिकली सही, मल्टी-लाइन स्ट्रिंग से युक्त हो।

विभिन्न प्रकार के वाक्यविन्यास हैं जिनका उपयोग किया जा सकता है। उदाहरण के लिए, चूंकि कमांडों को पाइप किया जा सकता है bashऔर sh, और शायद अन्य गोले भी, सरलतम उपाय यह है कि sshशेल इनवोकेशन को केवल हेरेडोक्स के साथ संयोजित करें:

ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

ध्यान दें कि उपरोक्त को बिना निष्पादित किए/bin/bash चेतावनी में परिणाम होगा Pseudo-terminal will not be allocated because stdin is not a terminal। यह भी ध्यान दें कि EOTसिंगल-कोट्स से घिरा हुआ है, जिससे कि हर्डोक को अबडॉक केbash रूप में पहचाना जाता है , स्थानीय चर प्रक्षेप को बंद कर दिया जाता है ताकि कमांड टेक्स्ट को जैसे-जैसे पास किया जाएगा ssh

यदि आप पाइप के प्रशंसक हैं, तो आप निम्नानुसार फिर से लिख सकते हैं:

cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

/bin/bashऊपर के बारे में एक ही चेतावनी लागू होती है।

एक अन्य मान्य तरीका है, मल्टी-लाइन रिमोट कमांड को एक स्ट्रिंग के रूप में पास करना, जो कि bashवेरिएबल इंटरपोलेशन की कई परतों का उपयोग करता है:

ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"

उपरोक्त समाधान निम्नलिखित तरीके से इस समस्या को हल करता है:

  1. ssh user@serverबैश द्वारा पार्स किया गया है, और होने की व्याख्या की है sshआदेश, उसके बाद एक तर्क user@serverको पास करने की sshकमान

  2. "एक प्रक्षेपित स्ट्रिंग शुरू करता है, जिसे पूरा करने पर sshकमांड में पारित करने के लिए एक तर्क शामिल होगा , जिसे इस मामले में व्याख्या sshकरने के लिए दूरस्थ कमांड के रूप में समझा जाएगाuser@server

  3. $( निष्पादित होने के लिए एक कमांड शुरू करता है, जिसमें आउटपुट आसपास के प्रक्षेपित स्ट्रिंग द्वारा कब्जा कर लिया जाता है

  4. catजो कुछ भी फाइल है उसकी सामग्री को आउटपुट करने के लिए एक कमांड है। के उत्पादन को catवापस प्रक्षेपित स्ट्रिंग में कैप्चर किया जाएगा

  5. <<एक बैश वंशानुगत शुरू होता है

  6. 'EOT'निर्दिष्ट करता है कि हेरेडोक का नाम ईओटी है। 'ईओटी के आस-पास के एकल उद्धरण निर्दिष्ट करते हैं कि हेरेडोक को अबडॉक के रूप में पार्स किया जाना चाहिए , जो हेरेडोक का एक विशेष रूप है जिसमें सामग्री को बैश द्वारा प्रक्षेपित नहीं किया जाता है, बल्कि शाब्दिक प्रारूप में पारित किया जाता है

  7. किसी भी सामग्री के बीच में सामना किया है <<'EOT'और <newline>EOT<newline>nowdoc उत्पादन में जोड़ा जाएगा

  8. EOTNowdoc को समाप्त करता है, जिसके परिणामस्वरूप एक nowdoc अस्थायी फ़ाइल बनाई जा रही है और कॉलिंग catकमांड पर वापस भेज दी गई है । catNowdoc को आउटपुट करता है और आउटपुट को इंटरपोल किए गए स्ट्रिंग को कैप्चर करने के लिए वापस करता है

  9. ) निष्पादित करने के लिए आदेश समाप्त करता है

  10. "कैप्चरिंग इंटरपोलेटेड स्ट्रिंग को समाप्त करता है। प्रक्षेपित स्ट्रिंग की सामग्री sshको एक एकल कमांड लाइन तर्क के रूप में वापस पारित किया sshजाएगा , जो दूरस्थ कमांड के रूप में निष्पादित करने के लिए व्याख्या करेगाuser@server

यदि आपको बाहरी उपकरणों का उपयोग करने से बचने की आवश्यकता है cat, और एक के बजाय दो बयानों को ध्यान में न रखें, readSSH कमांड उत्पन्न करने के लिए एक हेरेडोक के साथ अंतर्निहित का उपयोग करें :

IFS='' read -r -d '' SSH_COMMAND <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

ssh user@server "${SSH_COMMAND}"

+1 डेढ़ साल बाद! :) वास्तव में स्पष्ट व्याख्या। अच्छी तरह से किया
यरोस्लावटीर

1
मेरे लिए (और मैं किसी भी तरह से "DevOps" व्यक्ति नहीं हूं) यह वही है जो काम कर रहा है (मैं जेनकिंस का उपयोग कर रहा हूं)। मैंने "-t -t" और "-T" सुझावों की भी कोशिश की, लेकिन खुले धारा मुद्दों और गैर-निष्पादन मुद्दों में भाग गया।
रयान क्रू 21

2 साल बाद, वास्तव में उपयोगी
जैक-नी

+1 विस्मयकारी व्याख्या। लेकिन अगर आप अंतिम कोड स्निपेट (IFS = '' *) दूरस्थ कमांड को निष्पादित करने के लिए एक फ़ंक्शन बनाते हैं, तो आप $ 1 को IFS = '' * में कैसे पास करेंगे? यह बिल्कुल $ 1 की सामग्री को पहचानता है।
क्रिस्टियन मैथियास अंबेक

1
@ mklement0 ज़रूर, आप जरूरत के अनुसार तार से बच सकते हैं, लेकिन जो स्क्रिप्ट विवरणों को संशोधित करने के झंझट से बचना चाहता है, वह आपको किसी अन्य शेल स्क्रिप्ट से कॉपी करना और चिपकाना हो सकता है, या उस मामले के लिए स्टैकओवरफ़्लो? इसके अलावा, catसमाधान की शान यह है कि यह एकल (यद्यपि यौगिक) कथन में पूरा किया जाता है, और शेल वातावरण को प्रदूषित करने वाले अस्थायी चर में परिणाम नहीं करता है।
देजय क्लेटन

63

मैं इस उत्तर को जोड़ रहा हूं क्योंकि यह एक संबंधित समस्या को हल करता है जो मुझे एक ही त्रुटि संदेश के साथ हो रहा था।

समस्या : मैंने विंडोज के तहत साइबरविन स्थापित किया था और यह त्रुटि हो रही थी:Pseudo-terminal will not be allocated because stdin is not a terminal

रिज़ॉल्यूशन : यह पता चला है कि मैंने ओपनशेड क्लाइंट प्रोग्राम और यूटिलिटीज़ को स्थापित नहीं किया था । क्योंकि साइबरविन ssh के विंडोज कार्यान्वयन का उपयोग कर रहा था, न कि साइबर संस्करण का। इसका समाधान था ओपनशग्विन पैकेज स्थापित करना।


10
मेरे लिए यह पता चला कि यह पाथ में एक और ssh कार्यान्वयन था:$ which ssh/cygdrive/c/Program Files (x86)/Git/bin/ssh
FelixJongleur42

और इसे स्थापित करने opensshका तरीका विंडोज के लिए जाने का तरीका हो सकता है: superuser.com/a/301026/260710
एंड्रियास डिट्रिच

यह समाधान मेरे लिए काम करता है। Openshsh स्थापित करने के बाद, समस्या दूर हो गई है।
2

34

चेतावनी संदेश Pseudo-terminal will not be allocated because stdin is not a terminal.इस तथ्य के कारण है कि कोई sshदस्तावेज़ निर्दिष्ट नहीं किया गया है जबकि स्टडिन को यहां दस्तावेज़ से पुनर्निर्देशित किया गया है। एक निर्दिष्ट कमांड की कमी के कारण एक तर्क के रूप में sshपहले एक इंटरेक्टिव लॉगिन सत्र की उम्मीद है (जिसमें दूरस्थ होस्ट पर एक pty के आवंटन की आवश्यकता होगी) लेकिन फिर यह महसूस करना होगा कि इसका स्थानीय स्टेंट कोई tty / pty नहीं है। sshयहाँ एक दस्तावेज़ से पुनर्निर्देशन को आम तौर पर एक आदेश के रूप में /bin/shनिर्दिष्ट करने के लिए (जैसे ) की आवश्यकता होती है ssh- और ऐसे मामले में डिफ़ॉल्ट रूप से दूरस्थ होस्ट पर कोई भी आबंटित नहीं किया जाएगा।

चूँकि इसके माध्यम से निष्पादित करने के लिए कोई कमांड नहीं sshहै, जिसके लिए tty / pty की उपस्थिति की आवश्यकता होती है (जैसे कि vimया तो top) -tस्विच को अलग करना sshहै। बस उपयोग करें ssh -T user@server <<EOT ...या ssh user@server /bin/bash <<EOT ...चेतावनी दूर हो जाएगी।

तो <<EOFबच गए नहीं है या एकल उद्धृत (यानी <<\EOTया <<'EOT'यहाँ दस्तावेज़ के अंदर) चर से पहले ही निष्पादित हो रहा है स्थानीय खोल से विस्तार किया जाएगा ssh ...। इसका प्रभाव यह है कि यहाँ दस्तावेज़ के अंदर चर खाली रहेंगे क्योंकि वे केवल दूरस्थ शेल में परिभाषित हैं।

इसलिए, यदि $REL_DIRस्थानीय शेल द्वारा दोनों को एक्सेस किया जाना चाहिए और रिमोट शेल में परिभाषित किया जाना चाहिए , तो कमांड के $REL_DIRपहले यहां दस्तावेज़ के बाहर परिभाषित किया जाना चाहिए ssh( संस्करण 1 नीचे); या, अगर <<\EOTया <<'EOT'उपयोग किया जाता है, तो sshकमांड का आउटपुट REL_DIRअगर sshstdout को कमांड का एकमात्र आउटपुट echo "$REL_DIR"यहां बच / सिंगल-कोटेड यहाँ दस्तावेज़ ( नीचे संस्करण 2 ) द्वारा उत्पन्न किया जा सकता है ।

एक तीसरा विकल्प यहां दस्तावेज़ को एक चर में संग्रहीत करना होगा और फिर इस चर को कमांड तर्क के रूप में ssh -t user@server "$heredoc"( नीचे संस्करण 3 ) पास करना होगा।

और, अंतिम लेकिन कम से कम, यह जांचने के लिए कोई बुरा विचार नहीं होगा कि दूरस्थ होस्ट पर निर्देशिका सफलतापूर्वक बनाई गई थी (देखें: जांच करें कि क्या फ़ाइल ssh के साथ दूरस्थ होस्ट पर मौजूद है )।

# version 1

unset DEP_ROOT REL_DIR
DEP_ROOT='/tmp'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR="${DEP_ROOT}/${datestamp}"

ssh localhost /bin/bash <<EOF
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
#echo "$REL_DIR"
exit
EOF

scp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"


# version 2

REL_DIR="$(
ssh localhost /bin/bash <<\EOF
DEP_ROOT='/tmp'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR="${DEP_ROOT}/${datestamp}"
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
echo "$REL_DIR"
exit
EOF
)"

scp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"


# version 3

heredoc="$(cat <<'EOF'
# -onlcr: prevent the terminal from converting bare line feeds to carriage return/line feed pairs
stty -echo -onlcr
DEP_ROOT='/tmp'
datestamp="$(date +%Y%m%d%H%M%S)"
REL_DIR="${DEP_ROOT}/${datestamp}"
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
echo "$REL_DIR"
stty echo onlcr
exit
EOF
)"

REL_DIR="$(ssh -t localhost "$heredoc")"

scp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"

5
इस त्रुटि का क्या अर्थ है और क्यों यह एक हेरेडोक का उपयोग करते समय दिखाई दे रहा है, इस पर बहुत विस्तृत विवरण के लिए धन्यवाद, इससे मुझे वास्तव में इसे समझने में मदद मिली, बजाय इसके चारों ओर काम करने के।
दान

29

सभी प्रासंगिक जानकारी मौजूदा उत्तरों में है, लेकिन मुझे एक संक्षिप्त सारांश का प्रयास करने दें :

tl; डॉ:

  • कमांड-लाइन तर्क का उपयोग करके चलाने के लिए आदेश पारित करें :
    ssh jdoe@server '...'

    • '...' तार कई पंक्तियों को फैला सकते हैं, इसलिए आप यहां एक दस्तावेज़ के उपयोग के बिना भी अपना कोड पढ़ सकते हैं:
      ssh jdoe@server ' ... '
  • जब आप यहाँ दस्तावेज़ का उपयोग करते हैं, तो स्टड के माध्यम से कमांड पास न करें :
    ssh jdoe@server <<'EOF' # Do NOT do this ... EOF

कमांड को तर्क के रूप में पास करना-के रूप में कार्य करता है, और:

  • छद्म टर्मिनल के साथ समस्या भी उत्पन्न नहीं होगी।
  • आपकोexit अपने आदेशों के अंत में एक बयान की आवश्यकता नहीं होगी , क्योंकि कमांड संसाधित होने के बाद सत्र स्वचालित रूप से बाहर निकल जाएगा।

संक्षेप में: स्टड के माध्यम से कमांड पास करना एक ऐसा तंत्र है जो sshडिजाइन के साथ बाधाओं पर है और समस्याओं का कारण बनता है जिन्हें तब काम करना चाहिए।
आगे पढ़ें, अगर आप और जानना चाहते हैं


वैकल्पिक पृष्ठभूमि जानकारी:

sshलक्ष्य सर्वर पर निष्पादित करने के लिए कमांड स्वीकार करने का तंत्र एक कमांड-लाइन तर्क है : अंतिम ऑपरेंड (गैर-विकल्प तर्क) एक स्ट्रिंग को एक या अधिक शेल कमांड स्वीकार करता है।

  • डिफ़ॉल्ट रूप से, ये कमांड बिना ( इंटरैक्टिव छद्म) टर्मिनल (विकल्प -Tनिहित है) के उपयोग के बिना, गैर-संवादात्मक शेल में अप्राप्य चलता है , और अंतिम कमांड के पूरा होने पर सत्र स्वतः समाप्त हो जाता है।

  • इस घटना में कि आपके कमांड को उपयोगकर्ता की सहभागिता की आवश्यकता होती है , जैसे कि एक इंटरैक्टिव प्रॉम्प्ट का जवाब देना, आप स्पष्ट रूप से एक pty (pseudo-tty) , एक छद्म टर्मिनल के निर्माण का अनुरोध कर सकते हैं , जो -tविकल्प का उपयोग करके दूरस्थ सत्र के साथ बातचीत करने में सक्षम बनाता है; उदाहरण के लिए:

    • ssh -t jdoe@server 'read -p "Enter something: "; echo "Entered: [$REPLY]"'

    • ध्यान दें कि इंटरएक्टिव readप्रॉम्प्ट केवल एक पाइट के साथ सही ढंग से काम करता है, इसलिए -tविकल्प की आवश्यकता होती है।

    • एक pty का उपयोग करने का एक उल्लेखनीय दुष्प्रभाव है: stdout और stderr संयुक्त होते हैं और दोनों stdout के माध्यम से रिपोर्ट किए जाते हैं ; दूसरे शब्दों में: आप नियमित और त्रुटि आउटपुट के बीच अंतर खो देते हैं; उदाहरण के लिए:

      • ssh jdoe@server 'echo out; echo err >&2' # OK - stdout and stderr separate

      • ssh -t jdoe@server 'echo out; echo err >&2' # !! stdout + stderr -> stdout

इस तर्क की अनुपस्थिति में, sshएक इंटरेक्टिव शेल बनाता है - जब आप स्टड के माध्यम से कमांड भेजते हैं , जो कि परेशानी शुरू होती है:

  • एक इंटरेक्टिव शेल के लिए, sshआम तौर पर डिफ़ॉल्ट रूप से एक पेंटी (छद्म टर्मिनल) आवंटित किया जाता है, सिवाय इसके कि स्टड एक (वास्तविक) टर्मिनल से जुड़ा नहीं है।

    • Stdin के माध्यम से कमांड भेजने का मतलब है कि sshstdin अब किसी टर्मिनल से नहीं जुड़ा है, इसलिए कोई pty नहीं बना है, और आपको इसके अनुसार ssh चेतावनी देता है :
      Pseudo-terminal will not be allocated because stdin is not a terminal.

    • यहां तक ​​कि -tविकल्प, जिसका एक्सप्रेस उद्देश्य एक पैटी के निर्माण का अनुरोध करना है , इस मामले में पर्याप्त नहीं है : आपको एक ही चेतावनी मिलेगी।

      • थोड़ा उत्सुकता से, आपको तब एक pty के निर्माण के लिए विकल्प को दोगुना-t करना होगा : ssh -t -t ...या ssh -tt ...पता चलता है कि आप वास्तव में, वास्तव में इसका मतलब है

      • शायद इस बहुत ही जानबूझकर कदम की आवश्यकता के लिए तर्क यह है कि चीजें उम्मीद के मुताबिक काम नहीं कर सकती हैं । उदाहरण के लिए, macOS 10.12 पर, उपरोक्त कमांड के स्पष्ट समकक्ष, स्टैडेन के माध्यम से कमांड प्रदान करना और उपयोग करना -tt, ठीक से काम नहीं करता है; readप्रॉम्प्ट के जवाब के बाद सत्र अटक जाता है :
        ssh -tt jdoe@server <<<'read -p "Enter something: "; echo "Entered: [$REPLY]"'


उस अप्रत्याशित घटना में, जिसे आप एक तर्क के रूप में पारित करना चाहते हैं, कमांड लाइन को आपके सिस्टम के लिए बहुत लंबा बना देता है (यदि इसकी लंबाई आती है getconf ARG_MAX- यह लेख देखें ), पहले स्क्रिप्ट के रूप में रिमोट सिस्टम के कोड को कॉपी करने पर विचार करें ( का उपयोग कर, जैसे,scp ), और फिर उस स्क्रिप्ट को निष्पादित करने के लिए एक आदेश भेजें।

एक चुटकी में, का उपयोग करें -T, और एक अनुगामी आदेश के साथ, स्टड के माध्यम से आदेश प्रदान करें exit, लेकिन ध्यान दें कि यदि आपको इंटरैक्टिव विशेषताओं की आवश्यकता है, तो -ttबदले में -Tकाम नहीं कर सकता है।


1
यह पूरी तरह से काम करता है, लेकिन यह ssh के माध्यम से हर कमांड को टर्मिनल डिस्प्ले भेज रहा है।
मार्क ई

1
"एक पीटीआई के निर्माण के लिए डबल-टी विकल्प: ssh -t -t ... या ssh -tt ... से पता चलता है कि आप वास्तव में, वास्तव में इसका मतलब है।" - हा, हा - यह हास्यास्पद है, लेकिन गंभीर भी धन्यवाद - मैं अपने सिर को डबल टी के आसपास नहीं पा सकता हूं मुझे पता है कि अगर मैं एक ही टी में डाल देता हूं तो यह नहीं होता है
डेविड जेसी

22

मुझे नहीं पता कि लटका कहाँ से आता है, लेकिन पुनर्निर्देशन (या पाइपिंग) एक इंटरैक्टिव ssh में कमांड सामान्य रूप से समस्याओं का एक नुस्खा है। कमांड-टू-रन-ए-ए-लास्ट-तर्क शैली का उपयोग करना और स्क्रिप्ट को ssh कमांड पर पास करना अधिक मजबूत है:

ssh user@server 'DEP_ROOT="/home/matthewr/releases"
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR=$DEP_ROOT"/"$datestamp
if [ ! -d "$DEP_ROOT" ]; then
    echo "creating the root directory"
    mkdir $DEP_ROOT
fi
mkdir $REL_DIR'

(सभी एक विशाल में ' बहुस्तरीय कमांड लाइन तर्क)।

छद्म टर्मिनल संदेश आपकी वजह से है, -tजो ssh को रिमोट मशीन पर चलने वाले वातावरण को वहां चलने वाले कार्यक्रमों के लिए वास्तविक टर्मिनल की तरह बनाने की कोशिश करने के लिए कहता है। आपका ssh क्लाइंट ऐसा करने से इंकार कर रहा है क्योंकि उसका स्वयं का मानक इनपुट टर्मिनल नहीं है, इसलिए उसके पास रिमोट मशीन से विशेष टर्मिनल APIs को स्थानीय अंत में आपके वास्तविक टर्मिनल पर पास करने का कोई तरीका नहीं है।

-tवैसे भी आप क्या हासिल करने की कोशिश कर रहे थे ?


1
-T विकल्प, Psuedo टर्मिनल समस्या को ठीक करने का प्रयास था (यह काम नहीं करता था)। मैंने आपके समाधान की कोशिश की, इसे पीडो टर्मिनल चीज़ से छुटकारा मिल गया, लेकिन अब यह सिर्फ लटका हुआ है ...
मैथ्यू

4
@ हेनिंग: क्या आप एक इंटरैक्टिव ssh में पुनर्निर्देशन या पाइपिंग के नुकसान के बारे में विस्तार से बता सकते हैं या लिंक प्रदान कर सकते हैं?
आइजैक क्लेमन

थोड़ा देर से लेकिन: यहां आपको एक छद्म टर्मिनल की आवश्यकता नहीं है, इसलिए -Tइसके बजाय विकल्प का उपयोग करें ।
फ्लोरियन कैस्टेलन

6

इन उत्तरों के बहुत सारे पढ़ने के बाद मुझे लगा कि मैं अपने परिणामी समाधान को साझा करूंगा। सब मैंने जोड़ा है/bin/bash वह हेरेडोक पहले है और यह अब त्रुटि नहीं देता है।

इसे इस्तेमाल करो:

ssh user@machine /bin/bash <<'ENDSSH'
   hostname
ENDSSH

इसके बजाय (त्रुटि देता है):

ssh user@machine <<'ENDSSH'
   hostname
ENDSSH

या इसका उपयोग करें:

ssh user@machine /bin/bash < run-command.sh

इसके बजाय (त्रुटि देता है):

ssh user@machine < run-command.sh

अतिरिक्त :

यदि आप अभी भी एक दूरस्थ संवादात्मक संकेत चाहते हैं, जैसे कि यदि आप जिस स्क्रिप्ट को चला रहे हैं वह आपको पासवर्ड या अन्य जानकारी के लिए संकेत देती है, क्योंकि पिछले समाधान आपको संकेतों में टाइप करने की अनुमति नहीं देंगे।

ssh -t user@machine "$(<run-command.sh)"

और अगर आप भी पूरे सत्र को एक फ़ाइल में लॉग इन करना चाहते हैं logfile.log:

ssh -t user@machine "$(<run-command.sh)" | tee -a logfile.log

0

मैं विंडोज के तहत एक ही त्रुटि रहा था emacs 24.5.1 का उपयोग करके कुछ कंपनी के सर्वर से / ssh: user @ host के माध्यम से कनेक्ट करने के लिए। मेरी समस्या का हल "ट्रम्प-डिफाल्ट-मेथड" वैरिएबल को "पलक" में सेट कर रहा था और जब भी मैं किसी सर्वर से जुड़ता हूं तो मैं ssh प्रोटोकॉल को ommit करता हूं। इस कार्य के लिए आपको PuTTY का plink.exe इंस्टॉल करना होगा।

समाधान

  1. Mx अनुकूलित-चर (और फिर हिट मारा)
  2. ट्रम्प-डिफ़ॉल्ट-विधि (और फिर हिट फिर से दर्ज करें)
  3. टेक्स्ट फ़ील्ड पर पलक लगाएं और फिर बफर को लागू करें और सहेजें
  4. जब भी मैं एक दूरस्थ सर्वर का उपयोग करने की कोशिश करता हूं तो मैं अब Cxf / user @ होस्ट का उपयोग करता हूं: और फिर पासवर्ड इनपुट करता हूं। कनेक्शन अब विंडोज पर एमएसीएस के तहत मेरे रिमोट सर्वर पर सही ढंग से बनाया गया है।

-3

ssh -t foobar @ लोकलहोस्ट yourcript.pl


2
ओपी -tभी उपयोग करता है, लेकिन उनके विशिष्ट परिदृश्य में यह पर्याप्त नहीं है, जिसने प्रश्न को शुरू करने के लिए प्रेरित किया।
mklement0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.