एक SSH सत्र के अंदर SSH के दौरान कई कमांड


10

मेरे पास एक स्थानीय मशीन है, जिसे किसी दूरस्थ masterमशीन को SSH सत्र बनाना है और फिर masterकुछ रिमोट में से प्रत्येक के लिए एक और आंतरिक SSH सत्र slaves, और फिर एक विशिष्ट निर्देशिका को हटाने के लिए 2 कमांडों को निष्पादित करना है और इसे फिर से बनाना है।

ध्यान दें कि स्थानीय मशीन में मास्टर के पास पासवर्ड रहित एसएसएच है और दास के पास मास्टर के पास पासवर्ड रहित एसएसएच है। साथ ही सभी होस्टनाम .ssh/configस्थानीय / मास्टर मशीनों के लिए जाने जाते हैं और दासों के होस्टनाम slaves.txtस्थानीय स्तर पर हैं और मैं उन्हें वहां से पढ़ता हूं।

तो मैं क्या करता हूँ और काम करता है:

username="ubuntu"
masterHostname="myMaster"
while read line
do

    #Remove previous folders and create new ones.
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition""
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "mkdir -p EC2_WORKSPACE/$project Input Output Partition""


    #Update changed files...
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""

done < slaves.txt 

यह क्लस्टर Amazon EC2 पर है और मैंने देखा है कि प्रत्येक पुनरावृत्ति में 6 SSH सत्र बनाए गए हैं जो एक महत्वपूर्ण देरी को प्रेरित करता है। मैं कम SSH कनेक्शन प्राप्त करने के लिए इन 3 कमांडों को 1 में जोड़ना चाहता हूं। इसलिए मैंने पहले 2 कमांड को संयोजित करने का प्रयास किया

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

लेकिन यह उम्मीद के मुताबिक काम नहीं करता है। यह पहले एक ( rm -rf Input Output Partition) को निष्पादित करने के लिए लगता है और फिर सत्र से बाहर निकलता है और आगे बढ़ता है। मैं क्या कर सकता हूँ?


3
आदेश में इस तरह के अप्रत्यक्ष के बजाय आप -Jविकल्प का उपयोग कर सकते हैं जो आपके कूदने वाले मेजबान को परिभाषित करेगा।
हौलेथ

जवाबों:


15

विचार करें कि &&एक तार्किक ऑपरेटर है। इसका मतलब यह नहीं है कि "इस कमांड को भी चलाएं" इसका मतलब है "इस कमांड को चलाएं अगर दूसरा सफल हो गया"।

इसका मतलब है कि यदि rmकमांड विफल रहता है (जो कि तीन निर्देशिकाओं में से किसी में भी मौजूद नहीं है) तो mkdirनिष्पादित नहीं किया जाएगा। यह उस व्यवहार की तरह नहीं है जिसे आप चाहते हैं; यदि निर्देशिका मौजूद नहीं है, तो संभवतः उन्हें बनाना ठीक है।

उपयोग ;

अर्धविराम ;का प्रयोग आज्ञाओं को अलग करने के लिए किया जाता है। आदेश क्रमिक रूप से चलाए जाते हैं, अगले पर जारी रखने से पहले प्रत्येक की प्रतीक्षा कर रहे हैं, लेकिन उनकी सफलता या विफलता का एक दूसरे पर कोई प्रभाव नहीं पड़ता है।

भीतर के उद्धरण से बचिए

अन्य उद्धरण के अंदर उद्धरण से बच जाना चाहिए, अन्यथा आप एक अतिरिक्त समाप्ति बिंदु और प्रारंभ बिंदु बना रहे हैं। आपकी आज्ञा:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

हो जाता है:

ssh -n $username@$masterHostname "ssh -t -t $username@$line \"rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input OutputPartition\""

आपके वर्तमान आदेश, क्योंकि बच गए उद्धरणों की कमी को पूरा करना चाहिए:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition

यदि वह सफल होता है:

mkdir -p EC2_WORKSPACE/$project Input Output Partition"" # runs on your local machine

आप देखेंगे कि सिंटैक्स हाइलाइटिंग पूरे कमांड को यहाँ पर लाल दिखाता है, जिसका अर्थ है कि पूरा कमांड स्ट्रिंग ssh को पास किया जा रहा है। अपने स्थानीय मशीन की जाँच करें; आपके पास निर्देशिकाएं हो सकती हैं Input Outputऔर Partitionजहां आप इसे चला रहे थे।


मैं आपकी बातों को समझता हूं। एक हिस्सा जिसे मैंने दोहराया था वह अर्धविराम था, क्योंकि मैंने सोचा था कि यह एक ही समय में 1 से अधिक कमांड निष्पादित करेगा, यही कारण है कि मैंने इसका उपयोग नहीं किया।
mgus

अर्धविराम कमांड को निष्पादित करने का कारण नहीं बनेगा एक ही समय में कमांड निष्पादित करने के लिए एक संदर्भ के रूप में यहां देखें । &कारणों आदेशों पूर्णांक वह पृष्ठभूमि है, जो साधन वे अगले पर जाने से पहले समाप्त करने के लिए इंतजार कर रहे थे जा नहीं होते चलाने के लिए।
Centimane

10

आप हमेशा OpenSSH में अपने जंपबॉक्स मल्टीप्लेक्सिंग में परिभाषित कर सकते हैं

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

SSH मल्टीप्लेक्सिंग के साथ एक फायदा यह है कि नए TCP कनेक्शन बनाने का ओवरहेड समाप्त हो जाता है। एक मशीन द्वारा स्वीकार किए जा सकने वाले कनेक्शनों की समग्र संख्या एक परिमित संसाधन है और सीमा कुछ मशीनों पर दूसरों की तुलना में अधिक ध्यान देने योग्य है, और लोड और उपयोग दोनों के आधार पर बहुत भिन्न होती है। नया कनेक्शन खोलते समय भी काफी देरी होती है। मल्टीप्लेक्सिंग का उपयोग करके बार-बार नए कनेक्शन खोलने वाली गतिविधियों में काफी वृद्धि की जा सकती है।

इसके लिए में करें /etc/ssh/ssh_config:

ControlMaster auto
ControlPath ~/.ssh/controlmasters/ssh_mux_%h_%p_%r
ControlPersist 30m

इस तरह, अगले 30 मिनट में एक ही सर्वर से किए गए किसी भी कनेक्शन को पिछले ssh कनेक्शन का पुन: उपयोग किया जाएगा।

आप इसे मशीन या मशीनों के समूह के लिए भी परिभाषित कर सकते हैं। दिए गए लिंक से लिया गया।

Host machine1
    HostName machine1.example.org
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 10m

यह तो दिलचस्प है! क्या किसी दिए गए कनेक्शन के लिए इसे स्पष्ट रूप से चालू और बंद करने का कोई तरीका है? ऐसा लगता है कि इस एक उपयोग के मामले के लिए सभी SSH कनेक्शनों में बहुत अधिक परिवर्तन हो जाता है। क्या इसका उपयोग अधिक सटीक तरीके से किया जा सकता है? केवल एक निश्चित कनेक्शन को बहुसंकेतन शुरू करने के लिए?
सेंटिमेन

@ सेंटिमेन हां, ने जवाब अपडेट किया
रुई एफ रिबेरो

1
मैं एक दुनिया पढ़ने-लिखने योग्य के बजाय उपयोगकर्ता के घर में सॉकेट लगाने का सुझाव दूंगा /tmp/
हेमायल

@heemayl अच्छा बिंदु। कंप्यूटर में होने पर मैं इसे संपादित करूंगा।
रुई एफ रिबेरो

@RuiFRibeiro इसके अलावा, की तरह दिखता है के अनुसार man ssh, ControlPath, ControlMasterऔर ControlPersistमान्य विकल्प एक पारित करने के लिए कर रहे हैं sshका उपयोग कर आदेश -o। एक और भी अधिक सटीक उपयोग का मामला हो सकता है, sshस्क्रिप्ट के पहले हिस्से में मल्टीप्लेक्सिंग स्थापित करें और इसे दूसरों के लिए रीसायकल करें, लेकिन अन्यथा प्रदर्शन दंड से बचें। मुझे आश्चर्य है कि 3 एसएसएच कनेक्शन के लिए वीएस मल्टीप्लेक्सिंग का बेंचमार्क क्या नहीं है, यह देखते हुए कि "नया कनेक्शन खोलते समय भी महत्वपूर्ण देरी होती है"
सेंटिमेन

4

आप अपने सभी कमांड को अपने "मास्टर" सर्वर पर एक अलग स्क्रिप्ट में डाल सकते हैं।

मास्टर स्क्रिप्ट

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"

फिर अपने ssh स्क्रिप्ट में इसे इस तरह से कहें: SSH स्क्रिप्ट

username="ubuntu"
masterHostname="myMaster"
while read line
do
ssh -n $username@$masterHostname "ssh -t -t $username@$line < /path/to/masterscript.sh"
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""
done < slaves.txt 

या यदि सभी फाइलें प्रारंभिक मशीन पर होनी चाहिए तो आप ऐसा कुछ कर सकते हैं:

script1

script2="/path/to/script2"
username="ubuntu"
while read line; do
cat $script2 | ssh -t -t $username@line
done < slaves.txt

script2

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"
rsync --delete -avzh "/EC2_NFS/$project/* EC2_WORKSPACE/$project"

ssh स्क्रिप्ट

script1="/path/to/script1"
username="ubuntu"
masterHostname="myMaster"
cat $script1 | ssh -n $username@$masterHostname

1

कुछ समय पहले, मेरे पास नियंत्रण सॉकेट्स का उपयोग करने का अवसर था जैसे अन्य उत्तर सुझाते हैं (यह उत्तर अनिवार्य रूप से इस उत्तर की तरह नियंत्रण सॉकेट्स का उपयोग करने का एक संयोजन है और इस उत्तर जैसी स्क्रिप्ट्स )।

उपयोग का मामला हैक था: authorized_keysलक्षित उपयोगकर्ता का समय-समय पर एक निर्धारित कार्य द्वारा अधिलेखित किया गया था और मैं उस फ़ाइल में कुछ जोड़ने के लिए लाल-टेप के माध्यम से चीजों को जल्दी से परीक्षण करना चाहता था। इसलिए मैं थोड़ी देर के लूप को सेटअप करूंगा, जिसमें जरूरत के अनुसार उस फाइल की कुंजी जुड़ गई, मेरा परीक्षण चला, और लूप को रद्द कर दिया। हालाँकि, एक छोटी खिड़की होगी जहाँ निर्धारित कार्य फ़ाइल को अधिलेखित कर देगा और मेरा लूप अभी भी अंतर्ग्रहण होगा sleep। इसलिए, शुरुआत में एक कंट्रोल सॉकेट स्थापित करना मेरी स्क्रिप्ट SSH को बाद में समस्याओं के बिना जाने देगा:

#! /bin/bash -xe
. "${CONFIG_DIR}/scripts/setup-ssh.sh"

# Build and test
export TEST_LABEL="${_started_by}-${BUILD_TAG%-BUILD*}"
#...
xargs --arg-file test-list \
    --no-run-if-empty \
    --process-slot-var=NUM \
    --max-procs=${#SERVERS[@]} \
    --max-args="${BATCH_SIZE:-20}" \
    "${CONFIG_DIR}/scripts/run-test.sh"

कहाँ setup-ssh.shहै:

export SSH_CONFIG="${CONFIG_DIR}/scripts/.ssh-config"
mapfile -t SERVERS < "${CONFIG_DIR}/scripts/hosts"

for SERVER in "${SERVERS[@]}"
do
    while ! ssh -F "${SSH_CONFIG}" "${SERVER}" -fnN; do sleep 1; done
    scp -F "${SSH_CONFIG}" "${CONFIG_DIR}/scripts/ssh-script.sh" "${SERVER}":"${TEST_LABEL}.sh"
done

और .ssh-config:

Host test-*
  User test
  StrictHostKeyChecking no
  ControlMaster auto
  ControlPath /tmp/ssh-%h-%p-%r

और run-test.sh:

mapfile -t TEST_SERVERS < "${CONFIG_DIR}/scripts/hosts"
ssh -F "${SSH_CONFIG}" "${TEST_SERVERS[$NUM]}" "./${TEST_LABEL}.sh"

अनुक्रम इस प्रकार है:

  • मुख्य स्क्रिप्ट (पहले दिखाए गए) स्रोत setup-ssh.sh
  • setup-ssh.shव्यस्त-छोरों को सर्वर तब तक बंद कर देता है जब तक कि सभी में एक नियंत्रण सॉकेट सेटअप न हो। hostsफ़ाइल बस प्रत्येक पंक्ति में सर्वर होस्ट नामों एक सूचीबद्ध करता है।
  • चूंकि कंट्रोल सॉकेट निर्दिष्ट करने वाला कॉन्फ़िगरेशन केवल तभी ${CONFIG_DIR}/scripts/.ssh-configतक है, जब तक कि मैं उस फ़ाइल का उपयोग करके निर्दिष्ट नहीं करता -F, SSH कनेक्शन इसका उपयोग नहीं करेंगे। तो यह मुझे नियंत्रण सॉकेट का उपयोग करने की अनुमति देता है जहां मुझे Fविकल्प का उपयोग करने की आवश्यकता होती है ।
  • सेटअप स्क्रिप्ट सर्वर पर परीक्षण निष्पादन स्क्रिप्ट की प्रतिलिपि भी बनाती है। निष्पादन स्क्रिप्ट में आदेशों का एक समूह होता है, और क्योंकि मैंने निष्पादन स्क्रिप्ट की प्रतिलिपि बनाई है, मुझे SSH के लिए उद्धृत करने की एक अतिरिक्त परत के बारे में चिंता करने की ज़रूरत नहीं है (और जब विस्तार हो जाता है, तो यह पता लगाने के लिए अतिरिक्त संज्ञानात्मक ओवरहेड)।
  • फिर मुख्य स्क्रिप्ट का उपयोग xargsसर्वर पर कार्यभार को वितरित करने के लिए किया जाता है, जैसे ही नए काम शुरू होते हैं, जैसे ही वे समाप्त होते हैं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.