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?
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.
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
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.
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é.
<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)
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).
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://bash.cyberciti.biz/security/expect-ssh-login-script /
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
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"
si vous voulez exécuter une commande comme celle-ci
temp=`ls -a`
echo $temp
commande dans ` va provoquer des erreurs.
ci-dessous résoudra ce problème
ssh user@host '''
temp=`ls -a`
echo $temp
'''
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.