écrire un script shell en ssh sur une machine distante et exécuter des commandes


97

J'ai deux questions:

  1. Il existe plusieurs machines Linux distantes, et j'ai besoin d'écrire un script shell qui exécutera le même ensemble de commandes dans chaque machine. (Y compris certaines opérations sudo). Comment cela peut-il être fait à l'aide de scripts shell?
  2. Lors de la connexion à la machine distante, comment gérer le moment où il demande une authentification d'empreinte digitale RSA.

Les machines distantes sont des machines virtuelles créées à la volée et je n'ai que leurs adresses IP. Donc, je ne peux pas placer un fichier de script au préalable dans ces machines et les exécuter à partir de ma machine.


Je pense à déployer un programme de type agent dans des machines Linux distantes, qui maintiennent la connexion avec le serveur par une connexion réseau (ou SSL) / par interrogation périodique du serveur.
Raptor

Je n'ai besoin d'exécuter un ensemble de commandes qu'une seule fois, il n'est donc pas nécessaire de maintenir la connexion
Balanivash

"aucun script" signifie "aucun fichier du tout", je suppose? Comment gérez-vous l'authentification? Vous pouvez désactiver la vérification des empreintes digitales de l'hôte (voir ma réponse), mais vous obtenez toujours une invite de mot de passe interactive si vous n'avez pas configuré de clé publique / privée.
Andreas Fester

1
Andreas: oui. pas de fichiers du tout. l'invite passwd peut être gérée en utilisant expectcomme `expect" ? assword: "`
Balanivash

Réponses:


141

Il existe plusieurs machines Linux distantes, et j'ai besoin d'écrire un script shell qui exécutera le même ensemble de commandes dans chaque machine. (Y compris certaines opérations sudo). Comment cela peut-il être fait à l'aide de scripts shell?

Vous pouvez le faire avec ssh, par exemple:

#!/bin/bash
USERNAME=someUser
HOSTS="host1 host2 host3"
SCRIPT="pwd; ls"
for HOSTNAME in ${HOSTS} ; do
    ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"
done

Lors de la connexion à la machine distante, comment gérer le moment où il demande une authentification d'empreinte digitale RSA.

Vous pouvez ajouter l' StrictHostKeyChecking=nooption à ssh:

ssh -o StrictHostKeyChecking=no -l username hostname "pwd; ls"

Cela désactivera la vérification de la clé d'hôte et ajoutera automatiquement la clé d'hôte à la liste des hôtes connus. Si vous ne souhaitez pas que l'hôte soit ajouté au fichier d'hôtes connus, ajoutez l'option-o UserKnownHostsFile=/dev/null .

Notez que cela désactive certains contrôles de sécurité , par exemple la protection contre les attaques man-in-the-middle. Il ne doit donc pas être appliqué dans un environnement sensible à la sécurité.


Quel est le langage de script? Vous pouvez bien sûr également appeler à sshpartir de n'importe quel script shell
Andreas Fester

Et si vous voulez également faire un CTRL + C et continuer ssh sur plusieurs serveurs ?. par exemple, dans certains serveurs, il demande un mot de passe et dans d'autres non, le script y restera donc bloqué. y a-t-il un moyen de faire quelque chose de similaire à -o pour faire un CTRL c ou CTRL d?
Chanafot le

5

Il existe plusieurs façons de gérer cela.

Ma méthode préférée est d'installer http://pamsshagentauth.sourceforge.net/ sur les systèmes distants ainsi que votre propre clé publique. (Trouvez un moyen de les installer sur la VM, vous avez en quelque sorte un système Unix entier installé, qu'est-ce que quelques fichiers de plus?)

Une fois votre agent ssh transféré, vous pouvez désormais vous connecter à chaque système sans mot de passe.

Et encore mieux, ce module pam s'authentifiera pour sudo avec votre paire de clés ssh afin que vous puissiez exécuter avec les droits root (ou tout autre utilisateur) si nécessaire.

Vous n'avez pas à vous soucier de l'interaction de la clé hôte. Si l'entrée n'est pas un terminal, ssh limitera simplement votre capacité à transférer les agents et à vous authentifier avec des mots de passe.

Vous devriez également regarder dans les paquets comme Capistrano. Regardez certainement autour de ce site; il a une introduction aux scripts à distance.

Les lignes de script individuelles peuvent ressembler à ceci:

ssh remote-system-name command arguments ... # so, for exmaple,
ssh target.mycorp.net sudo puppet apply

4

Installez sshpass en utilisant, apt-get install sshpasspuis modifiez le script et mettez les adresses IP, les noms d'utilisateur et le mot de passe de vos machines Linux dans l'ordre respectif. Après cela, exécutez ce script. C'est tout ! Ce script installera VLC dans tous les systèmes.

#!/bin/bash
SCRIPT="cd Desktop; pwd;  echo -e 'PASSWORD' | sudo -S apt-get install vlc"
HOSTS=("192.168.1.121" "192.168.1.122" "192.168.1.123")
USERNAMES=("username1" "username2" "username3")
PASSWORDS=("password1" "password2" "password3")
for i in ${!HOSTS[*]} ; do
     echo ${HOSTS[i]}
     SCR=${SCRIPT/PASSWORD/${PASSWORDS[i]}}
     sshpass -p ${PASSWORDS[i]} ssh -l ${USERNAMES[i]} ${HOSTS[i]} "${SCR}"
done

utilisez $ SSHPASS pour exporter le mot de passe afin d'éviter de s'afficher dans le script. Ref: tecmint.com
Hexy

2

Si vous êtes capable d'écrire du code Perl, vous devriez envisager d'utiliser Net :: OpenSSH :: Parallel .

Vous seriez en mesure de décrire les actions qui doivent être exécutées dans chaque hôte de manière déclarative et le module se chargera de tous les détails effrayants. L'exécution de commandes via sudoest également prise en charge.


2

Ce travail pour moi.

Syntaxe: ssh -i pemfile.pem nom_utilisateur @ adresse_ip 'command_1; commande 2; commande 3 '

#! /bin/bash

echo "########### connecting to server and run commands in sequence ###########"
ssh -i ~/.ssh/ec2_instance.pem ubuntu@ip_address 'touch a.txt; touch b.txt; sudo systemctl status tomcat.service'

1

Pour ce genre de tâches, j'utilise à plusieurs reprises Ansible qui permet de dupliquer de manière cohérente des scripts bash dans plusieurs conteneurs ou VM. Ansible (plus précisément Red Hat ) dispose désormais d'une interface Web supplémentaire AWX qui est l'édition open-source de leur tour commerciale.

Ansible: https://www.ansible.com/
AWX: https://github.com/ansible/awx
Ansible Tower: produit commercial, vous explorerez probablement d'abord l'AWX open-source gratuit, plutôt que le free-trail de 15 jours de la tour


1

Il existe plusieurs façons d'exécuter les commandes ou le script sur les multiples machines Linux distantes. Un moyen simple et le plus simple est via pssh (programme parallèle ssh)

pssh : est un programme pour exécuter ssh en parallèle sur un certain nombre d'hôtes. Il fournit des fonctionnalités telles que l'envoi d'entrée à tous les processus, la transmission d'un mot de passe à ssh, l'enregistrement de la sortie dans des fichiers et le délai d'expiration.

Exemple et utilisation:

Connectez - vous à host1 et host2, et imprimez "hello, world" à partir de chacun:

 pssh -i -H "host1 host2" echo "hello, world"

Exécutez des commandes via un script sur plusieurs serveurs:

pssh -h hosts.txt -P -I<./commands.sh

Utilisation et exécution d'une commande sans vérifier ni enregistrer les clés d'hôte:

pssh -h hostname_ip.txt -x '-q -o StrictHostKeyChecking=no -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes' -i  'uptime; hostname -f'

Si le fichier hosts.txt a un grand nombre d'entrées, disons 100, l'option de parallélisme peut également être définie sur 100 pour garantir que les commandes sont exécutées simultanément:

pssh -i -h hosts.txt -p 100 -t 0 sleep 10000

Options :
-I: Lire l'entrée et l'envoyer à chaque processus ssh.
-P: Indique à pssh d'afficher la sortie à son arrivée.
-h: lit le fichier de l'hôte.
-H: [utilisateur @] hôte [: port] pour un seul hôte.
-i: affiche la sortie standard et l'erreur standard lorsque chaque hôte termine
-x args: transmet des arguments supplémentaires en ligne de commande SSH
-o option: peut être utilisé pour donner des options au format utilisé dans le fichier de configuration. (/ etc / ssh / ssh_config ) (~ / .ssh / config)
-p parallélisme: utilise le nombre donné comme nombre maximum de connexions simultanées
-q Mode silencieux: provoque la suppression de la plupart des messages d'avertissement et de diagnostic.
-t: rend les connexions expirées après le nombre de secondes donné. 0 signifie que pssh n'expirera aucune connexion

Lors de la connexion à la machine distante, comment gérer le moment où il demande une authentification d'empreinte digitale RSA.

Désactivez StrictHostKeyChecking pour gérer l'invite d'authentification RSA.
-o StrictHostKeyChecking = non

Source : homme pssh


0

Cela a fonctionné pour moi. J'ai fait une fonction. Mettez ceci dans votre script shell:

sshcmd(){
    ssh $1@$2 $3
}

sshcmd USER HOST COMMAND

Si vous avez plusieurs machines sur lesquelles vous souhaitez exécuter la même commande, vous répétez cette ligne avec un point-virgule. Par exemple, si vous avez deux machines, vous feriez ceci:

sshcmd USER HOST COMMAND ; sshcmd USER HOST COMMAND

Remplacez USER par l'utilisateur de l'ordinateur. Remplacez HOST par le nom de l'ordinateur. Remplacez COMMAND par la commande que vous souhaitez exécuter sur l'ordinateur.

J'espère que cela t'aides!


-1

Vous pouvez suivre cette approche:

  • Connectez-vous à une machine distante en utilisant Expect Script . Si votre machine ne prend pas en charge, attendez-vous à télécharger le même. L'écriture du script Expect est très simple (google pour obtenir de l'aide à ce sujet)
  • Mettez toutes les actions à effectuer sur le serveur distant dans un script shell.
  • Appelez le script shell distant à partir du script expect une fois la connexion réussie.

Comme je l'ai mentionné dans la question, les machines distantes sont créées en cours d'exécution et je ne peux pas avoir de script dans la machine au préalable.
Balanivash

Dans ce cas, mettez toutes les actions dans le script Expect. Le script Expect peut également exécuter des commandes sur un hôte distant.
rai.skumar
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.