रिमोट मशीन पर शेल स्क्रिप्ट चलाने के लिए SSH का उपयोग कैसे करें?


1220

मुझे रिमोट मशीन पर एक शेल स्क्रिप्ट (विंडोज़ / लिनक्स) चलाना है।

मैंने SSH को मशीन A और B दोनों पर कॉन्फ़िगर किया है। मेरी स्क्रिप्ट मशीन A पर है, जो मेरे कुछ कोड को रिमोट मशीन, मशीन B पर चलाएगी।

स्थानीय और दूरस्थ कंप्यूटर या तो विंडोज या यूनिक्स आधारित प्रणाली हो सकते हैं।

क्या पलक / एसश का उपयोग करके इसे चलाने का कोई तरीका है?


6
एक ही सवाल पहले से ही सर्वरफॉल्ट पर है: serverfault.com/questions/215756/… तो शायद इस सवाल का कोई मतलब नहीं है।
सेल्के

9
सर्वर फाल्ट पर सवाल के रूप में हालांकि कई जवाब नहीं है। हो सकता है कि यह सवाल उस एक को बदल दे।
बिग मैकलेरज्यूज

5
मुझे यह उत्तर व्यक्तिगत रूप से पसंद है: unix.stackexchange.com/questions/87405/…
mikevoermans

27
इसके अलावा यह स्पष्ट रूप से विषय पर होना चाहिए क्योंकि ssh सॉफ्टवेयर विकास के लिए एक प्रमुख उपकरण है।
static_rtti

4
कॉफी और ssh प्रश्न SO पर ऑफ-टॉपिक की समान डिग्री साझा नहीं करते हैं। फिर से खोलने के लिए वोट दिया गया।
विंसेंट कैंटिन

जवाबों:


1191

मशीन एक एक Windows बॉक्स है, तो आप plink (के हिस्से का उपयोग कर सकते पुट्टी -m पैरामीटर के साथ), और यह दूरस्थ सर्वर पर स्थानीय स्क्रिप्ट को निष्पादित करेंगे।

plink root@MachineB -m local_script.sh

यदि मशीन A एक यूनिक्स-आधारित प्रणाली है, तो आप इसका उपयोग कर सकते हैं:

ssh root@MachineB 'bash -s' < local_script.sh

आपको इसे चलाने के लिए स्क्रिप्ट को दूरस्थ सर्वर पर कॉपी नहीं करना चाहिए।


11
क्या -sविकल्प का उपयोग करने का कोई फायदा है ? यह मैन पेज मुझे विश्वास दिलाता है कि जब यह प्रसंस्करण विकल्प किया जाता है तो यह मानक इनपुट को संसाधित करेगा, चाहे -sइसका उपयोग किया जाए या नहीं।
एयरोटोटऑटो

78
एक स्क्रिप्ट के लिए जिसकी आवश्यकता होती है sudo, दौड़ें ssh root@MachineB 'echo "rootpass" | sudo -Sv && bash -s' < local_script.sh
bradley.ayers

6
@ bradley.ayers इतिहास को छोड़ने के लिए एक 'स्पेस' के साथ कमांड शुरू करना याद रखें (PS आपको HISTCONTROL=ignoreboth or ignorespaceइसे काम करने की आवश्यकता है )
derenio

8
@ bradley.ayers किन स्थितियों में आपको sudo की आवश्यकता होगी यदि आप पहले से ही रूट के रूप में लॉग इन कर रहे हैं?
ब्रायन श्लेनकर

21
@ एगोस्टिनो, आप इस तरह के पैरामीटर जोड़ सकते हैं: ssh root@MachineB ARG1="arg1" ARG2="arg2" 'bash -s' < local_script.sh क्रेडिट पूरी तरह से नीचे दिए गए @chubbsondubs 'उत्तर पर जाते हैं।
यवेस वान ब्रोकेवन

632

यह एक पुराना सवाल है, और जेसन का जवाब ठीक काम करता है, लेकिन मैं इसे जोड़ना चाहूंगा:

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

इसका उपयोग su और कमांड के साथ भी किया जा सकता है, जिसके लिए उपयोगकर्ता इनपुट की आवश्यकता होती है। (नोट 'बच गए हेरेडोक पर ध्यान दें )

संपादित करें: चूंकि यह उत्तर ट्रैफ़िक के बिट्स को प्राप्त करता रहता है, इसलिए मैं हेरेडोक के इस अद्भुत उपयोग के लिए और भी अधिक जानकारी जोड़ूंगा:

आप इस वाक्यविन्यास के साथ आदेशों को घोंसले में डाल सकते हैं, और ऐसा प्रतीत होता है कि केवल घोंसले के शिकार का काम होता है (एक सामान्य तरीके से)

ssh user@host <<'ENDSSH'
#commands to run on remote host
ssh user@host2 <<'END2'
# Another bunch of commands on another host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

आप वास्तव में टेलनेट, एफटीपी आदि जैसी कुछ सेवाओं के साथ बातचीत कर सकते हैं, लेकिन याद रखें कि हेरेडोक सिर्फ स्टड को पाठ के रूप में भेजता है, यह लाइनों के बीच प्रतिक्रिया की प्रतीक्षा नहीं करता है

संपादित करें: मुझे अभी पता चला है कि यदि आप उपयोग करते हैं तो आप इनडेस को टैब से इंडेंट कर सकते हैं <<-END!

ssh user@host <<-'ENDSSH'
    #commands to run on remote host
    ssh user@host2 <<-'END2'
        # Another bunch of commands on another host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(मुझे लगता है कि यह काम करना चाहिए)

Http://tldp.org/LDP/abs/html/here-docs.html भी देखें


4
आप इस तरह के रूप में लाइनों को जोड़कर थोड़ा अस्थायी कर सकते हैं: # $ (नींद 5)
ओलिवियर दुलक

50
ध्यान दें कि टर्मिनेटर ( <<'ENDSSH') के आसपास सिंगल कोट्स के साथ , स्ट्रिंग्स का विस्तार नहीं किया जाएगा, चर का मूल्यांकन नहीं किया जाएगा। तुम भी उपयोग कर सकते हैं <<ENDSSHया <<"ENDSSH"यदि आप विस्तार चाहते हैं।
मैकल

3
Expectउपयोग किया जा सकता है जब आपको एफ़टीपी जैसी इंटरैक्टिव कमांड को स्वचालित करने की आवश्यकता होती है।
प्रोग्रामथ्स

5
ध्यान दें कि मेरे पास एक Pseudo-terminal will not be allocated because stdin is not a terminal.संदेश था। इससे -t -tबचने के लिए किसी को params के साथ ssh का उपयोग करना होगा। इस धागे को SO
Buzut

8
यदि आप << - 'END' सिंटैक्स का उपयोग करने का प्रयास कर रहे हैं, तो सुनिश्चित करें कि आपका हेरेडोक समाप्त होने वाला सीमांकक TABs का उपयोग करने वाला है, न कि रिक्त स्थान का उपयोग करने वाला। ध्यान दें कि stackexchange से कॉपी / पेस्ट आपको स्पेस देगा। उन्हें टैब में बदलें और इंडेंट फीचर को काम करना चाहिए।
फीकलीन

249

इसके अलावा, यदि आप उन्हें गंतव्य होस्ट से चुनना चाहते हैं तो चर से बचना न भूलें।

इसने मुझे अतीत में पकड़ लिया है।

उदाहरण के लिए:

user@host> ssh user2@host2 "echo \$HOME"

प्रिंट / घर / उपयोगकर्ता 2

जबकि

user@host> ssh user2@host2 "echo $HOME"

प्रिंट / घर / उपयोगकर्ता

एक और उदाहरण:

user@host> ssh user2@host2 "echo hello world | awk '{print \$1}'"

"हैलो" को सही तरीके से प्रिंट करता है।


2
हालांकि निम्नलिखित के बारे में पता होना चाहिए: ssh user2@host 'bash -s' echo $HOME /home/user2 exit
इरेंट.इनफो

1
बस जोड़ने के लिए कि सत्र forमें चलने sshवाले लूप में लूप चर को बचाना नहीं चाहिए।
अलेक्सेयार्डिन

1
कई स्थितियों में, अपने पिछले उदाहरण को ठीक करने का तरीका ssh user2@host2 'echo hello world' | awk '{ print $1 }'स्थानीय स्तर पर Awk स्क्रिप्ट को चलाना होगा । यदि रिमोट कमांड आउटपुट के बारे में बहुत अधिक उत्पादन करता है, तो आप इसे स्थानीय सर्वर पर वापस कॉपी करने से बचना चाहते हैं, बेशक। संयोग से, रिमोट कमांड के आसपास सिंगल कोट्स किसी भी भागने की आवश्यकता से बचते हैं।
त्रिवेणी

151

यह YarekT के लिए एक विस्तार है, इनलाइन रिमोट कमांड को स्थानीय मशीन से दूरस्थ होस्ट पर ले जाने के साथ इनलाइन रिमोट कमांड को संयोजित करने के लिए ताकि आप रिमोट पर अपनी स्क्रिप्ट्स को पैरामीटर कर सकें:

ssh user@host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote host
  echo $ARG1 $ARG2
ENDSSH

मुझे यह सब एक लिपि में रखकर असाधारण रूप से मददगार लगा, इसलिए यह बहुत पठनीय और सुगम है।

यह क्यों काम करता है। ssh निम्नलिखित सिंटैक्स का समर्थन करता है:

ssh उपयोगकर्ता @ होस्ट Remote_command

बैश में हम पर्यावरण चर को एक लाइन पर कमांड चलाने से पहले परिभाषित करने के लिए निर्दिष्ट कर सकते हैं जैसे:

ENV_VAR_1 = 'value1' ENV_VAR_2 = 'value2' बैश -c 'echo $ ENV_VAR_1 $ ENV_VAR_2'

इससे कमांड चलाने से पहले वेरिएबल को परिभाषित करना आसान हो जाता है। इस मामले में गूंज हमारी आज्ञा है जिसे हम चला रहे हैं। गूंज से पहले सब कुछ पर्यावरण चर को परिभाषित करता है।

तो हम उन दो सुविधाओं और YarekT के उत्तर को पाने के लिए गठबंधन करते हैं:

ssh उपयोगकर्ता @ होस्ट ARG1 = $ ARG1 ARG2 = $ ARG2 'बैश -s' << 'ENDSSK' ...

इस मामले में हम ARG1 और ARG2 को स्थानीय मूल्यों पर सेट कर रहे हैं। उपयोगकर्ता @ होस्ट के बाद दूरस्थ_कमांड के रूप में सब कुछ भेज रहा है। जब दूरस्थ मशीन कमांड को कार्यान्वित करती है ARG1 और ARG2 स्थानीय मान सेट करते हैं, स्थानीय कमांड लाइन मूल्यांकन के लिए धन्यवाद, जो दूरस्थ सर्वर पर पर्यावरण चर को परिभाषित करता है, तो उन चर का उपयोग करके bash -s कमांड निष्पादित करता है। देखा।


1
ध्यान दें कि यदि आप ar -a जैसे पास करना चाहते हैं तो उपयोग कर सकते हैं -। जैसे 'ssh user @ host - -a foo bar' bash -s '<script.sh'। और आर्ग्स रीडायरेक्ट के बाद भी जा सकते हैं जैसे 'ssh user @ host' bash -s '<script.sh - -a foo bar'।
गौइथे

8
यदि किसी भी env var मान में रिक्त स्थान हैं, तो उपयोग करें:ssh user@host "ARG1=\"$ARG1\" ARG2=\"$ARG2\"" 'bash -s' <<'ENDSSH'...
TalkLittle

जैसा कि मैंने एक और टिप्पणी में लिखा है, उपयोग -sकरने का बहुत बिंदु स्क्रिप्ट के लिए तर्कों को लागू करने में सक्षम होना है जो स्टड के माध्यम से खट्टे होते हैं। मेरा मतलब है, यदि आप इसका उपयोग नहीं करने जा रहे हैं तो आप इसे छोड़ सकते हैं। यदि आप इसका उपयोग करते हैं, तो पर्यावरण चर का उपयोग करने का कोई कारण नहीं है:ssh user@host 'bash -s value1 value2' <<< 'echo "$@"'
JoL

104
<hostA_shell_prompt>$ ssh user@hostB "ls -la"

जब तक आपने अपने hostA उपयोगकर्ता की सार्वजनिक कुंजी को user.ssh की निर्देशिका के घर पर अधिकृत_की फ़ाइल में कॉपी नहीं किया है, पासवर्ड के लिए आपको संकेत देगा। यह पासवर्ड रहित प्रमाणीकरण के लिए अनुमति देगा (यदि ssh सर्वर के विन्यास पर एक सामान्य विधि के रूप में स्वीकार किया जाता है)


3
आपको वोट दिया। यह एक वैध उपाय है। जाहिर है, कुंजियों को संरक्षित किया जाना चाहिए, लेकिन उन्हें सर्वर साइड के माध्यम से पासवर्ड की तरह अमान्य भी किया जा सकता है।
१०:४४

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

निश्चित नहीं है, लेकिन क्या आप इस पद्धति का उपयोग करके hostB पर चलाने के लिए hosta पर अपनी स्क्रिप्ट को पाइप नहीं कर सकते हैं?
nevets1219

27

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


11

दौड़ने की कोशिश करो ssh user@remote sh ./script.unx


8
यह तभी काम करता है जब स्क्रिप्ट रिमोट पर डिफ़ॉल्ट (होम) डायरेक्टरी में हो। मुझे लगता है कि सवाल यह है कि रिमोट पर स्थानीय रूप से संग्रहीत स्क्रिप्ट को कैसे चलाया जाए।
मेटासिम

1
ssh username @ ip "chmod + x script.sh" <br/> ssh username @ ip "रिमोट होस्ट में फाइल भेजने का रास्ता"
मणि


8

मान लें कि आप इसे "स्थानीय" मशीन से स्वचालित रूप से करना चाहते हैं, तो मैन्युअल रूप से "रिमोट" मशीन में प्रवेश किए बिना, आपको एक टीसीएल एक्सटेंशन में देखना चाहिए जिसे एक्सपेक्ट के रूप में जाना जाता है, यह इस तरह की स्थिति के लिए सटीक रूप से डिज़ाइन किया गया है। मैंने SSH के माध्यम से लॉग-इन / इंटरैक्ट करने के लिए एक स्क्रिप्ट का लिंक भी प्रदान किया है।

https://www.nist.gov/services-resources/software/expect

http://bash.cyberciti.biz/security/expect-ssh-login-script/


5

मैं एक दूरस्थ मशीन पर एक शेल स्क्रिप्ट चलाने के लिए इसका उपयोग करता हूं (/ बिन / बैश पर परीक्षण किया गया):

ssh deploy@host . /home/deploy/path/to/script.sh

3
ssh user@hostname ".~/.bashrc;/cd path-to-file/;.filename.sh"

पर्यावरण फ़ाइल (.bashrc / .bashprofile / .profile) को स्रोत करने के लिए अत्यधिक अनुशंसित है। दूरस्थ होस्ट में कुछ चलाने से पहले क्योंकि टारगेट और स्रोत मेजबान पर्यावरण चर को ख़राब कर सकते हैं।


यह नहीं बताता है कि स्थानीय स्क्रिप्ट को दूरस्थ होस्ट में कैसे स्थानांतरित किया जाए।
किर्लगिन

2

यदि आप temp=`ls -a` echo $temp `` में इस कमांड की तरह कमांड निष्पादित करना चाहते हैं, तो त्रुटियों का कारण होगा।

नीचे दिए गए आदेश इस समस्या को हल करेंगे ssh user@host ''' temp=`ls -a` echo $temp '''


1

यहाँ उत्तर ( https://stackoverflow.com/a/2732991/4752883 ) बहुत अच्छा काम करता है अगर आप एक रिमोट लाइनक्स मशीन का उपयोग करके plinkया एक स्क्रिप्ट चलाने की कोशिश कर रहे हैं ssh। यह काम करेगा अगर स्क्रिप्ट पर कई लाइनें हैं linux

** हालांकि, यदि आप एक स्थानीय linux/windowsमशीन पर स्थित एक बैच स्क्रिप्ट को चलाने की कोशिश कर रहे हैं और आपकी रिमोट मशीन है Windows, और इसमें ** का उपयोग करके कई पंक्तियों का समावेश है

plink root@MachineB -m local_script.bat

काम नहीं करेगा।

केवल स्क्रिप्ट की पहली पंक्ति निष्पादित की जाएगी। यह शायद एक सीमा है plink

समाधान 1:

एक बहुस्तरीय बैच स्क्रिप्ट को चलाने के लिए (विशेषकर यदि यह अपेक्षाकृत सरल है, जिसमें कुछ लाइनें शामिल हैं):

यदि आपकी मूल बैच स्क्रिप्ट इस प्रकार है

cd C:\Users\ipython_user\Desktop 
python filename.py

आप अपनी local_script.batफ़ाइल में निम्नानुसार "&&" विभाजक का उपयोग करके लाइनों को एक साथ जोड़ सकते हैं : https://stackoverflow.com/a/8055390/4752883 :

cd C:\Users\ipython_user\Desktop && python filename.py

इस परिवर्तन के बाद, आप @ जेसन.चूम द्वारा यहाँ बताई गई स्क्रिप्ट चला सकते हैं: https://stackoverflow.com/a/2732991/4752883 इसके साथ:

`plink root@MachineB -m local_script.bat`

समाधान 2:

यदि आपकी बैच स्क्रिप्ट अपेक्षाकृत जटिल है, तो बैच स्क्रिप्ट का उपयोग करना बेहतर हो सकता है, जो पलक कमांड को इनकैप्सुलेट करता है और साथ ही साथ यहां बताया गया है @Martin https://stackoverflow.com/a/32196999/4752883 :

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe

1

यह बैश स्क्रिप्ट एक लक्ष्य रिमोट मशीन में ssh करता है, और रिमोट मशीन में कुछ कमांड चलाता है, इसे चलाने से पहले अपेक्षा को स्थापित करने के लिए मत भूलना (मैक पर brew install expect)

#!/usr/bin/expect
set username "enterusenamehere"
set password "enterpasswordhere"
set hosts "enteripaddressofhosthere"
spawn ssh  $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "somecommand on target remote machine here\n"
sleep 5
expect "$"
send -- "exit\n"

1
यदि आप पासवर्ड का उपयोग करना चाहते हैं तो यह बहुत अच्छा है ... हालाँकि घर पर किसी भी ssh कमांड को देखने वाले किसी भी व्यक्ति के लाभ के लिए, सार्वजनिक + निजी कुंजियों की एक जोड़ी का उपयोग नहीं करना चाहिए पासवर्ड ... एक बार पूरी तरह से पासवर्ड बंद करने के लिए अपने ssh सर्वर को अपडेट करें
स्कॉट स्टेंसलैंड

-1

आप धावकों का उपयोग कर सकते हैं :

sudo apt install runoverssh
runoverssh -s localscript.sh user host1 host2 host3...

-s एक स्थानीय स्क्रिप्ट को दूरस्थ रूप से चलाता है


उपयोगी झंडे:
-g सभी होस्ट के लिए एक वैश्विक पासवर्ड का उपयोग करें (सिंगल पासवर्ड प्रॉम्प्ट)
-nएसएसएचएस का उपयोग sshpass के बजाय, सार्वजनिक-विश्वसनीय प्रमाणीकरण के लिए उपयोगी


-24

सबसे पहले, स्कैप का उपयोग करके मशीन बी पर स्क्रिप्ट की प्रतिलिपि बनाएँ

[user @ machineA] $ scp / path / to / script user @ machineB: / home / user / path

फिर, केवल स्क्रिप्ट चलाएँ

[user @ machineA] $ ssh उपयोगकर्ता @ मशीनबी "/ घर / उपयोगकर्ता / पथ / स्क्रिप्ट"

यह काम करेगा यदि आपने स्क्रिप्ट को निष्पादन योग्य अनुमति दी है।


hi मैंने अनुशंसित शर्करा का उपयोग किया लेकिन यह मुझे निम्न त्रुटि देता है [oracle @ node1 ~] $ ssh oracle @ node2: ./ home / oracle / au / fs / conn.sh ssh: node2:। home / cacle / au / fs /। con.sh: नाम या सेवा ज्ञात नहीं [oracle @ node1 ~] $

'ssh oracle @ node2: ./ home / oracle / au / fs / conn.sh'? गलत कमांड लाइन, कमांड का नाम उपयोगकर्ता @ मेजबान भाग से एक अंतरिक्ष के साथ अलग होना चाहिए, न कि एक कॉलोन के साथ।
bortzmeyer

5
मैं इसे नीचा दिखा रहा हूं क्योंकि यह प्राथमिक दावा है कि इसे बिना कॉपी किए चलाया नहीं जा सकता, यह गलत है।
जेसन आर। कोम्ब्स

यह मददगार होता, जेसन ने कहा कि सिर्फ तथ्य बताने के बजाय यह गलत क्यों है। सहायक नहीं।
क्रिश

[user @ machineA] $ ssh रूट @ MachineB 'bash -s' </ machinea / पाथ / टू / स्क्रिप्ट
Oleksii Kyslytsyn
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.