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 SSH configuré sur les deux 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 basés sur Windows ou Unix.

Existe-t-il un moyen de faire cela en utilisant plink / ssh?

    Si la machine A est une boîte Windows, vous pouvez utiliser Plink (partie de PuTTY ) avec le paramètre -m et exécuter le script local sur le serveur distant.

    plink root@MachineB -m local_script.sh 

    Si la machine A est un système basé sur Unix, vous pouvez utiliser:

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

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

    C’est une vieille question, et la réponse de Jason fonctionne bien, mais j’aimerais append 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 de l'utilisateur. (notez le ' heredoc échappé)

    Edit: Etant donné que cette réponse continue à générer du trafic, j'appendai encore plus d'informations à cette utilisation merveilleuse de heredoc:

    Vous pouvez imbriquer des commandes avec cette syntaxe, et c'est la seule façon dont l'imbrication semble fonctionner (de manière sensée)

     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 réellement avoir une conversation avec certains services comme telnet, ftp, etc. Mais rappelez-vous que heredoc envoie simplement le stdin en tant que texte, il n'attend pas la 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

    De plus, n’oubliez pas d’échapper les variables si vous souhaitez les récupérer depuis l’hôte de destination.

    Cela m’a pris par le passé.

    Par exemple:

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

    imprime / home / utilisateur2

    tandis que

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

    imprime / accueil / utilisateur

    Un autre exemple:

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

    imprime “bonjour” correctement.

    Ceci est une extension de la réponse de YarekT pour combiner des commandes distantes en ligne avec le passage 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 extrêmement utile en gardant le tout dans un seul script, donc c'est très lisible et maintenable.

    Pourquoi cela fonctionne ssh prend en charge la syntaxe suivante:

    ssh user @ host remote_command

    Dans bash, nous pouvons spécifier les variables d'environnement à définir avant d'exécuter une commande sur une seule ligne, comme ceci:

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

    Cela facilite la définition des variables avant l'exécution d'une commande. Dans ce cas, echo est notre commande que nous exécutons. Tout ce qui précède l'écho définit les variables d'environnement.

    Nous combinons donc ces deux fonctionnalités et la réponse de YarekT pour obtenir:

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

    Dans ce cas, nous définissons ARG1 et ARG2 sur des valeurs locales. Tout envoyer après user @ host en tant que remote_command. Lorsque la machine distante exécute la commande ARG1 et ARG2, les valeurs locales sont définies, grâce à l'évaluation en 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. Voila.

     $ ssh user@hostB "ls -la" 

    Cela vous demandera un mot de passe, à moins que vous n’ayez copié la clé publique de votre utilisateur hostA dans le fichier authorized_keys sur la page d’accueil du répertoire de l’utilisateur .ssh. Cela permettra une authentification sans mot de passe (si elle est acceptée comme méthode d’authentification sur la configuration du serveur ssh)

    J’ai commencé à utiliser Fabric pour des opérations plus sophistiquées. Fabric nécessite Python et quelques autres dépendances, mais uniquement sur la machine cliente. Le serveur doit uniquement être un serveur ssh. Je trouve cet outil beaucoup plus puissant que les scripts shell transférés à SSH, et cela vaut la peine de le configurer (en particulier si vous aimez la programmation en Python). Fabric gère l’exécution de scripts sur plusieurs hôtes (ou hôtes de certains rôles), facilite les opérations idempotentes (telles que l’ajout d’une ligne à un script de configuration, mais pas s’il existe déjà) et permet la construction d’une logique plus complexe (telle que Python la langue peut fournir).

    En supposant que vous vouliez faire cela automatiquement depuis une machine “locale”, sans vous connecter manuellement à la machine “distante”, vous devriez examiner une extension TCL connue sous le nom d’Expect, conçue précisément pour ce type de situation. La page d’accueil ci-dessous est un peu minable, mais ne vous laissez pas décourager; J’ai également fourni un lien vers un script pour la connexion / interaction via SSH.

    http://expect.nist.gov/

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

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

    La réponse ici ( https://stackoverflow.com/a/2732991/4752883 ) fonctionne parfaitement 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 de commandes situé sur une machine linux/windows locale et que votre Windows distant est Windows , et qu’il comporte plusieurs lignes utilisant **

    plink root@MachineB -m local_script.bat

    ne travaillera pas

    Seule la première ligne du script sera exécutée. C’est probablement une limitation du plink .

    Solution 1:

    Pour exécuter un script de commandes multiligne (surtout s’il est relativement simple, composé de quelques lignes):

    Si votre script de lot d’origine est comme suit

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

    Vous pouvez combiner les lignes en utilisant le séparateur “&&” comme suit dans votre fichier local_script.bat : https://stackoverflow.com/a/8055390/4752883 :

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

    Après cette modification, 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 traitement par lots est relativement compliqué, il est préférable d’utiliser un script de traitement par lots qui encapsule la commande plink, comme indiqué ci-après 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 sur une machine distante cible et exécute des commandes sur la machine distante, n’oubliez pas d’installer expect avant de l’exécuter (sur l’ brew install expect 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" 

    Tout d’abord, copiez le script sur la machine B en utilisant scp

    [utilisateur @ machineA] $ scp / chemin / vers / script utilisateur @ machineB: / home / utilisateur / chemin

    Ensuite, lancez le script

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

    Cela fonctionnera si vous avez donné une autorisation d’exécution au script.