Première rédaction de cet article le 31 octobre 2007
Dernière mise à jour le 16 janvier 2008
Avec la disponibilité d'Unix pour des machines de bas prix comme les PC, l'ingénieur système a souvent besoin de maintenir N machines Unix identiques ou presque. Si N est de l'ordre de deux ou trois, cela peut encore se faire à la main, mais si N vaut vingt ou cent, cela n'est plus réaliste et il faut automatiser. Je présente ici la solution simpliste mais suffisante que j'utilise pour des salles temporaires, par exemple pour des formations comme les FFTI.
Le problème est connu depuis longtemps, même s'il n'avait pas été anticipé au début d'Unix, lorsqu'il y avait un seul ordinateur pour toute une université. Pour traiter ce problème, plusieurs solutions ont été proposées et la plus connue est certainement un programme très perfectionné, cfengine. cfengine permet de définir des classes de machine et de synchroniser les fichiers de configuration pour chaque classe. Il est très riche et je n'ai jamais eu le courage de l'apprendre. (Un logiciel du même genre est C3, que me recommande Olivier Ricou.)
Ma solution est plus bête et elle repose sur des petits scripts shell simples qui copient des fichiers depuis un maître vers des esclaves (ou bien qui exécutent des commandes sur tous les esclaves). On configure donc à la main une machine et on pousse ensuite sa configuraion vers toutes les autres.
Tous ces scripts lisent leur configuration dans le fichier
config-pc
dont voici un contenu typique (ici, les
quinze machines ont uniquement des adresses IPv6) :
start=131 end=145 prefix=2001:660:F108:1::
Les scripts dépendent de la commande Unix seq pour générer la liste des machines (notez que les différents scripts n'utilisent pas seq de la même manière, pour montrer la variété des possibilités) à partir d'un préfixe, d'un point de départ et d'un point d'arrivée. Cela nécessite donc que les adresses IP soient consécutives (pour une salle de TP, c'est une supposition raisonnable).
Ils utilisent ssh et, pour ne pas taper le
mot de passe à chaque fois, il faut, avant tout, configurer les
autorisations appropriées sur chaque machine (dans mon cas, en créant
le fichier ~root/.ssh/authorized_keys
dont le
contenu est ma clé publique, que je trouve dans
~/.ssh/id_dsa.pub
). Attention aux éventuels
problèmes de sécurité que cela peut poser, comme par exemple le fait
qu'il faut autoriser root en SSH (directive
PermitRootLogin
dans
sshd.conf
). Pour une salle de cours temporaire,
ce n'est pas trop grave.
Voici l'utilisation du script copy-each-pc
pour copier le fichier (ici /tmp/example
) vers le répertoire indiqué (ici /var/tmp
) :
% ./copy-each-pc /tmp/example /var/tmp
et le code du script :
#!/bin/sh . ./config-pc file=$1 destination=$2 if [ -z "$destination" ]; then echo "Usage: $0 file destination" exit 1 fi for host in $(seq -f ${prefix}%g $start $end); do echo "" echo "Copying \"$file\" to $host:$destination..." scp $file root@\[$host\]:$destination done
Notez les crochets autour de l'adresse IP pour scp, le deux-points étant utilisé
également pour séparer l'adresse du répertoire (HTTP a le même
problème donc un URL IPv6 ressemble à
http://[2001:660:f108:1::1]:8081/
, cf. RFC 2732). Ces crochets étant significatifs pour le shell, on doit
faire un échappement avec la barre inverse.
Et voici l'utilisation du script for-each-pc
,
ici pour exécuter la commande date sur tous les PC :
% ./for-each-pc "date"
et le code du script est :
#!/bin/sh . ./config-pc command=$1 if [ -z "$command" ]; then echo "Usage: $0 command" exit 1 fi for host in $(seq -f ${prefix}%g $start $end); do echo "" echo "Executing \"$command\" on $host..." ssh root@$host $command done
Prenons maintenant un script un peu plus compliqué, le script
v6-only
, qui copie sur toutes les machines un
fichier interfaces
avec l'adresse IPv6 de la
machine (oui, DHCP aurait été plus simple, mais
moins sûr et il rend les machines dépendantes du serveur DHCP). Ce
script est un peu plus compliqué car il copie un fichier
dont le contenu dépend de la machine. Il appelle donc sed pour faire
un remplacement dans le fichier maître, avant de copier le fichier
créé par sed vers la machine :
#!/bin/sh . ./config-pc for i in `seq $start $end`; do sed "s/TOKEN/$i/" etc/interfaces-v6only > /tmp/interfaces echo "Copying to $prefix$i..." scp /tmp/interfaces root@\[$prefix$i\]:/etc/network/interfaces ssh root@$prefix$i reboot done
Pour des scripts analogues, Ollivier Robert me suggère Dancer's Shell qui, en outre, permet le parallélisme des requêtes SSH et le contrôle de leur nombre. Olivier Perret propose un script qu'il a écrit, cdist, qui se configure via un fichier de configuration, script dont il précise qu'il est livré sans aucune garantie. Michel Casabona suggère une version parallèle (mon script est purement séquentiel) de ssh, pssh.
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)