$ wc -l /tmp/ossh.ips
21418 /tmp/ossh.ips
$ time ossh -n -h /tmp/ossh.ips -c uptime -p 1000 >/tmp/ossh.out
real 3m10.310s
user 0m30.970s
sys 0m19.282s
$ grep 'load average' /tmp/ossh.out | sort -n -k5 | tail -n1
10.23.91.97 [1] 13:37:55 up 828 days, 2:34, 0 users, load average: 8.29, 4.45, 3.90
$
Dans cet exemple, le fichier /tmp/ossh.ips contient 21418 adresses IP de machines. -n signifie que vous n'avez pas besoin d'effectuer des requêtes inversées pour déterminer le nom par adresse. -c uptime définit la commande que je souhaite exécuter. -p 1000 permet jusqu'à 1000 connexions en même temps. Comme vous pouvez le voir sur la sortie, la commande a fonctionné assez rapidement.
Que peut faire d'autre Ossh?
$ ossh -?
Usage: ossh [-?AinPv] [-c COMMAND] [-C COMMAND_FILE] [-H HOST_STRING] [-h HOST_FILE] [-I FILTER] [-k PRIVATE_KEY] [-l USER] [-o PORT] [-p PARALLELISM] [-T TIMEOUT] [-t TIMEOUT] [parameters ...]
-?, --help Show help
-A, --askpass Prompt for a password for ssh connects
-c, --command=COMMAND
Command to run
-C, --command-file=COMMAND_FILE
file with commands to run
-H, --host=HOST_STRING
Add the given HOST_STRING to the list of hosts
-h, --hosts=HOST_FILE
Read hosts from file
-i, --ignore-failures
Ignore connection failures in the preconnect mode
-I, --inventory=FILTER
Use FILTER expression to select hosts from inventory
-k, --key=PRIVATE_KEY
Use this private key
-l, --user=USER Username for connections [$LOGNAME]
-n, --showip In the output show ips instead of names
-o, --port=PORT Port to connect to [22]
-p, --par=PARALLELISM
How many hosts to run simultaneously [512]
-P, --preconnect Connect to all hosts before running command
-T, --connect-timeout=TIMEOUT
Connect timeout in seconds [60]
-t, --timeout=TIMEOUT
Run timeout in seconds
-v, --verbose Verbose output
$
La liste des hôtes peut être spécifiée soit directement sur la ligne de commande en utilisant l'option -H (dans le cas de plusieurs hôtes, ils doivent être séparés par un espace, et la liste entière doit être mise entre guillemets comme dans les exemples ci-dessous) ou chargé à partir d'un fichier à l'aide de l'option -h. Les lignes commençant par # dans le fichier sont ignorées. L'adresse peut contenir le port: my.host:2222. Vous pouvez utiliser l'extension d'accolade: "host {1,3..5} .com" deviendra "host1.com host3.com host4.com host5.com". -H et -h peuvent être utilisés plusieurs fois.
Pour l'autorisation sera utilisé
- le mot de passe que ossh demandera lors de l'utilisation de l'option -A
- commutateur ssh spécifié par l'option -k
- ssh-agent (dans ce cas, vous devez avoir défini la variable d'environnement SSH_AUTH_SOCK)
Dans cet ordre.
Parfois, vous devez vous assurer de pouvoir vous connecter à toutes les machines avant d'exécuter une commande. Il existe une option -P pour cela. Par défaut, si au moins une machine n'est pas disponible, ossh échouera. Si vous souhaitez ignorer les échecs de connexion, utilisez l'option -i.
Ossh peut utiliser votre système d'inventaire. Pour ce faire, les chemins doivent contenir la commande ossh-inventaire, à laquelle les paramètres de l'option -I seront passés. Cette option peut être utilisée plusieurs fois. La commande ossh-inventaire doit imprimer les lignes sur la sortie standard au format:
_ _
Où machine_address peut être un nom DNS ou une adresse IP.
Les commandes à exécuter sont spécifiées par les options -C (lire à partir du fichier) ou -c (prendre à partir de la ligne de commande). Ces options peuvent être utilisées plusieurs fois. Si -C et -c sont tous les deux présents, les commandes des fichiers seront exécutées en premier, puis à partir de la ligne de commande.
En plus d'exécuter simplement des commandes à l'aide d'ossh, vous pouvez diffuser des journaux en temps réel:
$ ossh -H "web05 web06" -c "tail -f -c 0 /var/log/nginx/access.log|grep --line-buffered Wget"
web05 192.168.1.23 - - [22/Jun/2016:12:24:02 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
web05 192.168.1.49 - - [22/Jun/2016:12:24:07 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
web06 192.168.1.117 - - [22/Jun/2016:12:24:23 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
web05 192.168.1.29 - - [22/Jun/2016:12:24:30 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"
...
Voici une simulation de déploiement progressif:
$ ossh -p 1 -H "test0{1..3}" -c "sleep 10 && date"
test01 Wed Jun 22 12:38:24 PDT 2016
test02 Wed Jun 22 12:38:34 PDT 2016
test03 Wed Jun 22 12:38:44 PDT 2016
$
On voit que les commandes sont exécutées séquentiellement sur les machines. Une seule machine est impliquée à la fois. Pour un déploiement réel, "sleep 10 && date" doit être remplacé par, par exemple, "apt-get install -y your_package".
C'est pour le déploiement que la toute première version d'ossh a été écrite. Quelqu'un me demandera pourquoi je n'ai pas utilisé un système de gestion de configuration généralement accepté? Le fait est que c'était en 2013 et nous avons utilisé le chef. Il était clair que le chef ne nous convenait pas en particulier avec l'incertitude quand exactement les changements seraient appliqués (le chef-client était exécuté toutes les 30 minutes). Afin de déployer systématiquement les changements sur de nombreuses machines, certains développeurs ont utilisé un sale hack: le chef-client ne fonctionnait pas tout le temps, mais n'était lancé une fois (via ssh) qu'au moment où il était nécessaire de faire le déploiement. Déjà à ce moment, des travaux étaient en cours pour remplacer le chef par du sel, mais la transition n'a pas été facile et son achèvement a nécessité du temps supplémentaire. Nous développions un nouveau service,qui a nécessité des déploiements fréquents et a été déployé par le seul paquet Debian. Tout d'abord, nous avons utilisé l'utilitaire de couteau du chef. Cet utilitaire vous permettait de vous connecter via ssh aux serveurs désirés et d'exécuter des commandes sur eux. À un moment donné, j'ai réalisé que chef dans ce cas est un lien supplémentaire et j'ai écrit ossh.
Il est important de noter que ossh est un outil pour résoudre des problèmes à grande échelle et non standard. Si le besoin d'utiliser ossh se présente souvent, c'est une raison de se demander si vous vous débrouillez bien avec l'infrastructure et la gestion des serveurs. Voici quelques situations dans lesquelles ossh m'a aidé personnellement:
- Une fois, j'ai rangé /root/.ssh/authorized_keys sur un grand nombre de serveurs (il y en avait environ 7000 à ce moment-là). Les développeurs y ont enregistré leurs clés, notamment pour les processus de mise à jour de leurs services. Il était nécessaire d'obtenir une liste de toutes les clés utilisées sur toutes les machines et de s'assurer que la suppression de ces clés ne serait pas catastrophique.
- Pour un saut de seconde sans douleur
- Lorsque nous étions aux prises avec TCP SACK PANIC , les règles iptables ont été déployées par le système de gestion de la configuration. Pour m'assurer que tout va bien, j'ai vérifié les règles correctes avec ossh. Et ce n'était pas du tout en vain, il y avait des voitures sur lesquelles les règles ne s'appliquaient pas.
- Parfois, je dois créer des environnements de test avec des centaines (et parfois des milliers) de machines. Souvent, ces machines sont isolées du réseau de production et ne sont pas disponibles pour le système de gestion de configuration standard. Dans de telles situations, la configuration de la machine peut être effectuée à l'aide de ossh.
Je prévois la question de savoir pourquoi je n'ai pas utilisé de solution toute faite. Comme je l'ai mentionné ci-dessus, la nécessité d'exécuter des commandes sur des milliers de machines m'est apparue pour la première fois en 2013. A cette époque, je n'ai pu trouver que des ssh parallèles, ce qui ne me convenait pas avec ce qui suit:
- Je n'ai pas pu augmenter le parallélisme au-dessus de 150, des erreurs ont commencé à se produire lors de la connexion à des serveurs distants
- parallel ssh a accumulé toutes les sorties et les a vidées une fois la commande terminée. Le streaming de journaux, par exemple, était impossible avec son aide
- La sortie ssh parallèle était (pour moi personnellement) difficile à analyser
À l'origine, ossh a été écrit en rubis, pour augmenter les performances, j'ai utilisé la machine événementielle, puis la fibre. J'ai récemment réécrit ossh to go. Je serais reconnaissant aux go-experts (je ne le suis pas pour le moment) de jeter un œil à mon code et d'indiquer les moyens possibles de l'améliorer.