Quelle est la manière la plus propre de ssh et d’exécuter plusieurs commandes dans Bash?

J’ai déjà un agent ssh configuré et je peux exécuter des commandes sur un serveur externe dans un script Bash comme:

ssh blah_server "ls; pwd;" 

Maintenant, ce que je voudrais vraiment faire, c’est exécuter beaucoup de longues commandes sur un serveur externe. Enfermer tous ces points entre guillemets serait assez moche, et je préférerais plutôt éviter de faire plusieurs fois pour éviter cela.

Alors, y a-t-il un moyen de le faire en une seule fois entre parenthèses ou quelque chose? Je cherche quelque chose du genre:

 ssh blah_server ( ls some_folder; ./someaction.sh; pwd; ) 

Fondamentalement, je serai heureux avec n’importe quelle solution aussi longtemps que c’est propre.

modifier

Pour clarifier, je parle de ceci faisant partie d’un script bash plus grand. D’autres personnes pourraient avoir besoin de gérer le script en fin de compte, alors je tiens à le garder propre. Je ne veux pas avoir un script bash avec une ligne qui ressemble à:

 ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';" 

parce que c’est extrêmement laid et difficile à lire.

Que diriez-vous d’un document Bash Here :

 ssh otherhost << EOF ls some_folder; ./someaction.sh 'some params' pwd ./some_other_action 'other params' EOF 

Pour éviter les problèmes mentionnés par @Globalz dans les commentaires, vous pourrez peut-être (en fonction de ce que vous faites sur le site distant) remplacer la première ligne par

 ssh otherhost /bin/bash << EOF 

Notez que vous pouvez effectuer une substitution de variable dans le document Here, mais vous devrez peut-être traiter des problèmes de cotation. Par exemple, si vous citez la "chaîne de limitation" (par exemple, EOF dans ce qui précède), vous ne pouvez pas effectuer de substitutions de variables. Mais sans citer la chaîne limite, les variables sont substituées. Par exemple, si vous avez défini $NAME ci-dessus dans votre script shell, vous pouvez le faire.

 ssh otherhost /bin/bash << EOF touch "/tmp/${NAME}" EOF 

et cela créerait un fichier sur la destination otherhost avec le nom de ce que vous avez assigné à $NAME . D'autres règles concernant les citations de scripts shell s'appliquent également, mais elles sont trop compliquées pour être utilisées ici.

Editez votre script localement, puis insérez-le dans ssh, par exemple

 cat commands-to-execute-remotely.sh | ssh blah_server 

commands-to-execute-remotely.sh ressemble à votre liste ci-dessus:

 ls some_folder ./someaction.sh pwd; 

Je vois deux façons:

D’abord, vous créez une prise de contrôle comme celle-ci:

  ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p  

et lance tes commandes

  ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p  -t  

De cette façon, vous pouvez écrire une commande ssh sans vous reconnecter au serveur.

Le second serait de générer dynamicment le script, en le scp et en le lançant.

Pour correspondre à votre exemple de code, vous pouvez envelopper vos commandes dans des simples ou doubles qoutes. Par exemple

 ssh blah_server " ls pwd " 

Cela peut également être fait comme suit. Placez vos commandes dans un script, nommons-le commands -inc.sh

 #!/bin/bash ls some_folder ./someaction.sh pwd 

Enregistrez le fichier

Maintenant, lancez-le sur le serveur distant.

 ssh user@remote 'bash -s' < /path/to/commands-inc.sh 

Jamais échoué pour moi.

Mettez toutes les commandes sur un script et il peut être exécuté comme

 ssh @ "bash -s" <./remote-commands.sh 

SSH et exécuter plusieurs commandes dans Bash.

Séparez les commandes par des points-virgules dans une chaîne, transmises à echo, toutes transférées dans la commande ssh. Par exemple:

 echo "df -k;uname -a" | ssh 192.168.79.134 Pseudo-terminal will not be allocated because stdin is not a terminal. Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda2 18274628 2546476 14799848 15% / tmpfs 183620 72 183548 1% /dev/shm /dev/sda1 297485 39074 243051 14% /boot Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux 

Cela fonctionne bien pour créer des scripts, car vous n’avez pas besoin d’inclure d’autres fichiers:

 #!/bin/bash ssh @ "bash -s" << EOF # here you just type all your commmands, as you can see, ie touch /tmp/test1; touch /tmp/test2; touch /tmp/test3; EOF 

Pour ceux qui se heurtent ici comme moi, j’ai réussi à échapper au point-virgule et à la nouvelle ligne:

Première étape: le point-virgule. De cette façon, nous ne cassons pas la commande ssh:

 ssh  echo test\;ls ^ backslash! 

Répertorié les hôtes distants / répertoire de base (connecté en tant que root), alors que

 ssh  echo test;ls ^ NO backslash 

répertorié le répertoire de travail en cours.

Prochaine étape: briser la ligne:

  v another backslash! ssh  echo test\;\ ls 

Ceci à nouveau répertorié le répertoire de travail à distance – formatage amélioré:

 ssh \ echo test\;\ ls 

Si vraiment plus beau que le document ici ou les citations autour des lignes brisées – eh bien, pas moi pour décider …

(Utilisation de bash, Ubuntu 14.04 LTS.)

Le moyen le plus simple de configurer votre système pour utiliser des sessions ssh uniques par défaut avec le multiplexage.

Cela peut être fait en créant un dossier pour les sockets:

 mkdir ~/.ssh/controlmasters 

Et puis en ajoutant ce qui suit à votre configuration .ssh:

 Host * ControlMaster auto ControlPath ~/.ssh/controlmasters/%r@%h:%p.socket ControlMaster auto ControlPersist 10m 

Maintenant, vous n’avez plus besoin de modifier votre code. Cela permet des appels multiples à ssh et scp sans créer de sessions multiples, ce qui est utile lorsque vous avez besoin de plus d’interaction entre vos machines locales et distantes.

Grâce à la réponse de @ terminus, http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/ et https://en.wikibooks.org / wiki / OpenSSH / Cookbook / Multiplexing .

Les réponses affichées en utilisant des chaînes multilignes et plusieurs scripts bash ne fonctionnaient pas pour moi.

  • Les longues chaînes multilignes sont difficiles à maintenir.
  • Les scripts bash séparés ne gèrent pas les variables locales.

Voici un moyen fonctionnel de ssh et d’exécuter plusieurs commandes tout en conservant le contexte local.

 LOCAL_VARIABLE=test run_remote() { echo "$LOCAL_VARIABLE" ls some_folder; ./someaction.sh 'some params' ./some_other_action 'other params' } ssh otherhost "$(set); run_remote"