Comment utiliser SSH pour exécuter un script shell sur une machine distante?

je dois exécuter un script shell (windows/Linux) sur une machine distante.

j'ai configuré SSH sur les machines A et B. mon script est sur la machine A qui exécutera une partie de mon code sur une machine distante, la machine B.

les ordinateurs locaux et distants peuvent être des systèmes Windows ou Unix.

y a-t-il un moyen d'exécuter do this using plink/ssh?

1038
demandé sur alpha_989 2008-11-20 14:44:25

12 réponses

si la Machine A est une fenêtre Windows, vous pouvez utiliser Plink (partie de PuTTY ) avec le paramètre-m, et il exécutera le script local sur le serveur distant.

plink root@MachineB -m local_script.sh

si la Machine A est un système Unix, vous pouvez utiliser:

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

Vous ne devriez pas avoir à copier le script sur le serveur distant à exécuter.

1050
répondu Jason R. Coombs 2010-04-28 21:00:03

C'est une vieille question, et la réponse de Jason fonctionne bien, mais je voudrais ajouter ceci:

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

cela peut également être utilisé avec su et les commandes qui nécessitent une entrée utilisateur. (notez le ' échappé heredoc)

Edit: puisque cette réponse ne cesse de recevoir des bouts de trafic, Je voudrais ajouter encore plus d'informations à cette utilisation merveilleuse de heredoc:

vous pouvez insérer des commandes avec cette syntaxe, et c'est la seule façon de au travail (en danger)

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

vous pouvez effectivement avoir une conversation avec certains services comme telnet, ftp, etc. Mais rappelez-vous qu'heredoc envoie simplement le stdin sous forme de texte, il n'attend pas de réponse entre les lignes

Edit: je viens de découvrir que vous pouvez indenter l'intérieur si vous utilisez <<-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

(je pense que cela devrait fonctionner)

Voir Aussi http://tldp.org/LDP/abs/html/here-docs.html

518
répondu Yarek T 2017-05-30 16:20:22

Aussi, n'oubliez pas d'échapper à des variables si vous voulez ramasser de l'hôte de destination.

cela m'a surpris dans le passé.

par exemple:

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

imprime /home/user2

alors que

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

imprime /home/user

autre exemple:

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

imprime "bonjour" correctement.

213
répondu dogbane 2008-11-20 12:25:35

il s'agit d'une extension de la réponse de YarekT pour combiner les commandes à distance en ligne avec la transmission des variables ENV de la machine locale à l'hôte distant afin que vous puissiez paramétrer vos scripts du côté distant:

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

j'ai trouvé cela exceptionnellement utile en gardant tout dans un script de sorte qu'il est très lisible et maintenable.

pourquoi ça marche. ssh supporte la syntaxe suivante:

SSH user@host remote_command

dans bash nous pouvons spécifier des variables d'environnement à définir avant d'exécuter une commande sur une seule ligne comme so:

ENV_VAR_1= 'value1' ENV_VAR_2= 'value2' bash-c 'echo $ ENV_VAR_1 $ ENV_VAR_2 '

qui rend facile de définir des variables avant d'exécuter une commande. Dans ce cas, echo est notre commandement. Tout ce qui précède echo définit les variables d'environnement.

nous combinons donc ces deux caractéristiques et la réponse de YarekT pour obtenir:

SSH user@host ARG1= $ ARG1 ARG2= $ ARG2 'bash-s' <<'ENDSSH'...

dans ce cas, nous réglons ARG1 et ARG2 aux valeurs locales. Envoyer tout après user@host comme le remote_command. Lorsque la machine distante exécute la commande ARG1 et ARG2, les valeurs locales sont définies, grâce à l'évaluation de la ligne de commande locale, qui définit les variables d'environnement sur le serveur distant, puis exécute la commande bash-s en utilisant ces variables. Le tour est joué.

130
répondu chubbsondubs 2017-08-01 14:59:36
<hostA_shell_prompt>$ ssh user@hostB "ls -la"

qui vous demandera un mot de passe, à moins que vous n'ayez copié la clé publique de votre hostA user sur le fichier authorized_keys de la maison de l'utilisateur .ssh du répertoire. Cela permettra une authentification sans mot de passe (si acceptée comme méthode auth sur la configuration du serveur ssh)

91
répondu Vinko Vrsalovic 2008-11-20 11:53:18

j'ai commencé à utiliser tissu pour des opérations plus sophistiquées. Fabric nécessite Python et quelques autres dépendances, mais seulement sur la machine client. Le serveur ne doit être qu'un serveur ssh. Je trouve que cet outil est beaucoup plus puissant que les scripts shell distribués à SSH, et vaut bien la peine d'être configuré (surtout si vous aimez programmer en Python). Fabric gère l'exécution de scripts sur plusieurs hôtes( ou hôtes de certains rôles), aide faciliter les opérations idempotent (comme ajouter une ligne à un script de configuration, mais pas si elle est déjà là), et permettre la construction de la logique plus complexe (comme le langage Python peut fournir).

24
répondu Jason R. Coombs 2016-11-18 14:13:18

en supposant que vous voulez dire que vous voulez faire cela automatiquement à partir d'une machine "locale", sans se connecter manuellement à la machine "distante", vous devriez regarder dans une extension TCL connue sous le nom D'Expect, il est conçu précisément pour ce genre de situation. C'est la page d'accueil ci-dessous qui semble un peu merdique, mais ne laissez pas cela vous dissuader; j'ai aussi fourni un lien vers un script pour se connecter/interagir via SSH.

http://expect.nist.gov /

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

8
répondu George Jempty 2008-11-20 12:10:10

Essayez d'exécuter ssh user@remote sh ./script.unx .

8
répondu Jeremy 2018-02-28 09:52:54

la réponse ici ( https://stackoverflow.com/a/2732991/4752883 ) fonctionne bien si vous essayez d'exécuter un script sur une machine linux distante en utilisant plink ou ssh . Cela fonctionnera si le script a plusieurs lignes sur linux .

* * cependant, si vous essayez d'exécuter un script batch situé sur un local linux/windows machine et votre machine à distance est Windows , et il se compose de lignes multiples en utilisant * *

plink root@MachineB -m local_script.bat

ne marchera pas.

seule la première ligne du script sera exécutée. C'est probablement un limitation de plink .

Solution 1:

pour exécuter un script de traitement par lots multilignes (surtout si c'est relativement simple), composé de quelques lignes):

si votre script de lot original est comme suit""

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

vous pouvez combinez les lignes ensemble en utilisant le séparateur "&&" comme suit dans votre local_script.bat fichier: https://stackoverflow.com/a/8055390/4752883 :

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

après ce changement, vous pouvez exécuter le script comme indiqué ici par @JasonR.Coombs: https://stackoverflow.com/a/2732991/4752883 avec:

`plink root@MachineB -m local_script.bat`

Solution 2:

si votre script de lot est relativement compliqué, il peut être préférable d'utiliser un lot script qui encapsule la commande plink ainsi que les éléments suivants comme indiqué ici par @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
0
répondu alpha_989 2018-04-21 03:53:49

ce script bash fait ssh dans une machine distante cible, et exécute une commande dans la machine distante, n'oubliez pas d'installer expect avant de l'exécuter (sur mac 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"
0
répondu Mohammed Rafeeq 2018-05-30 09:22:42

si vous voulez exécuter une commande comme celle-ci temp=`ls -a` echo $temp commande dans ` va provoquer des erreurs.

La commande

ci-dessous résoudra ce problème ssh user@host ''' temp=`ls -a` echo $temp '''

0
répondu Jinmiao Luo 2018-09-21 03:31:48

d'abord, Copiez le script sur la Machine B en utilisant scp

[user@machineA]$ scp /chemin/vers/le / script user@machineB:/home/user/path

ensuite, il suffit d'exécuter le script

[user@machineA]$ ssh utilisateur@machineB "/home/utilisateur/chemin/script"

cela fonctionnera si vous avez donné une permission exécutable au script.

-22
répondu Baishampayan Ghose 2015-07-08 17:38:45