478 votes

Quel est le moyen le plus propre de ssh et d'exécuter plusieurs commandes en Bash ?

J'ai déjà un agent ssh configuré, et je peux exécuter des commandes sur un serveur externe en Bash script en faisant des choses comme :

ssh blah_server "ls; pwd;"

Maintenant, ce que j'aimerais vraiment faire, c'est exécuter un grand nombre de commandes longues sur un serveur externe. Le fait de mettre toutes ces commandes entre guillemets serait assez laid, et je préférerais vraiment éviter de me connecter plusieurs fois au serveur pour éviter cela.

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

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

En fait, je me contenterai de n'importe quelle solution, pourvu qu'elle soit propre.

Editar

Pour clarifier, je parle du fait que cela fait partie d'un plus grand bash script. D'autres personnes pourraient avoir besoin de traiter le script plus tard, donc je voudrais le garder propre. Je ne veux pas avoir un script de bash avec une ligne qui ressemble à :

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

parce qu'il est extrêmement laid et difficile à lire.

2 votes

Hmm, et si on mettait tout ça dans un script sur le serveur et qu'on l'appelait avec un seul ssh invocation ?

1 votes

@Nikolai si les commandes dépendent du côté client, elles peuvent être écrites dans un shell script, puis scp , ssh et exécutez. C'est la façon la plus propre, je pense.

7 votes

Cela fait partie d'un plus grand bash script, donc je préfère ne pas le diviser avec la moitié vivant sur mon ordinateur personnel et l'autre moitié vivant sur le serveur et exécutée par ssh. Si possible, j'aimerais vraiment le garder comme un seul script exécuté depuis mon ordinateur personnel. N'y a-t-il vraiment aucun moyen propre d'encapsuler un ensemble de commandes dans un ssh ?

609voto

Paul Tomblin Points 83687

Que diriez-vous d'un Bash Document ici :

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 pouvez peut-être (en fonction de ce que vous faites sur le site distant) vous en sortir en remplaçant la première ligne par

ssh otherhost /bin/bash << EOF

Notez que vous pouvez effectuer des substitutions de variables dans le document Here, mais vous devrez peut-être faire face à des problèmes de citation. Par exemple, si vous citez la "chaîne limite" (ie. EOF dans l'exemple ci-dessus), alors vous ne pouvez pas faire 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 shell script, vous pourriez 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 la citation de l'interpréteur de commandes script s'appliquent également, mais sont trop compliquées pour être abordées ici.

6 votes

Ça ressemble exactement à ce que je veux ! Comment cela fonctionne-t-il ? Auriez-vous par hasard un lien vers une page qui l'explique ?

9 votes

+1 Je me disais justement ça -- voici un endroit où lire à ce sujet : tldp.org/LDP/abs/html/here-docs.html

1 votes

Lorsque j'utilise un heredoc comme celui-ci, le login "Message du jour" est envoyé à mon local. Existe-t-il un moyen d'empêcher l'affichage de ce message ?

160voto

bosmacs Points 4410

Éditez votre script localement, puis passez-le dans ssh, par ex.

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;

8 votes

Cela a le grand avantage que vous savez exactement ce qui est exécuté par le script distant - pas de problème de citation. Si vous avez besoin de commandes dynamiques, vous pouvez utiliser un shell script avec un subshell, toujours en pipant dans le ssh, i.e. ( echo $mycmd $myvar ; ...) | ssh myhost - comme avec l'utilisation de cat, vous savez exactement ce qui est envoyé dans le flux de commandes ssh. Et bien sûr, le sous-shell dans le script peut être multi-lignes pour plus de lisibilité - cf. linuxjournal.com/content/bash-sub-shells

9 votes

Pouvez-vous faire cela avec des arguments dans le commands-to-execute-remotely.sh ?

1 votes

Je pense que cette solution est bien plus utile que celle de Paultomblin. Puisque le script peut être redirigé vers n'importe quel serveur ssh sans avoir à ouvrir le fichier. De plus, c'est beaucoup plus lisible.

55voto

Andrei B Points 1583

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

ssh blah_server "
  ls
  pwd
"

0 votes

J'aime ce format, mais il n'est malheureusement pas utile pour stocker des données std dans une variable.

1 votes

Signus, que voulez-vous dire par "stocker des données std dans une variable" ?

1 votes

@Signus Il est parfaitement possible de faire ce que vous décrivez, même si vous voudrez probablement utiliser des guillemets simples au lieu de guillemets doubles autour des commandes distantes (ou échapper les opérateurs qui doivent être échappés entre guillemets doubles pour empêcher votre shell local de les intercepter et de les interpoler).

46voto

terminus Points 3966

Je vois deux façons :

D'abord vous faites une prise de contrôle comme ceci :

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

et exécutez vos commandes

 ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>

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

La seconde serait de générer dynamiquement le script, scp et de courir.

28voto

R J Points 54

Cela peut également se faire de la manière suivante. Mettez vos commandes dans un script, nommons-le commands-inc.sh

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

Sauvegarder le fichier

Maintenant, exécutez-le sur le serveur distant.

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

Il n'a jamais échoué pour moi.

0 votes

Similaire à ce que je pensais à l'origine ! Mais pourquoi est-ce que bash -s nécessaire ?

0 votes

Aussi, est-ce que #!/bin/bash vraiment utilisé ?

4 votes

Le -s est là pour la compatibilité. Extrait de man bash -s Si l'option -s est présente, ou si aucun argument ne subsiste après le traitement des options, alors les commandes sont lues depuis l'entrée standard. Cette option permet de définir les paramètres positionnels lors de l'invocation d'un shell interactif.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X