Tengo en casa un clúster de Raspberry Pi con Docker Swarm. Para no perder el control, todas usan la misma configuración: usuarios, versiones de Docker, etc.

A veces algunas actualizaciones requieren ejecutar lo mismo en todos los nodos del clúster, por ejemplo, crear una nueva red macvlan de Docker.

Para hacerlo, hay que ejecutar los mismos comandos en todos los nodos manualmente, entrando por ssh a cada uno, ejecutando los comandos y pasando al siguiente.

Como intento reducir mi trabajo a la larga y tener todo lo más organizado posible, empecé a buscar formas de ejecutar comandos en todos los nodos al mismo tiempo.

Iteración 1: un script de Python a medida

La primera iteración consistió en crear un script de Python propio. Por un lado, quería aprender un poco mejor Python; por otro, no encontraba una forma buena de ejecutar los comandos de manera más nativa.

Como cabe esperar (oigan, todavía tengo poca experiencia con el lenguaje 🙂), se convirtió en un desastre enorme muy rápido y se rompía con facilidad.

Tenía que encontrar otra manera de hacerlo, sin tener que volver a aprender lo que hice hace 3 semanas y lo que se rompió la última vez.

Iteración 2: pssh

Buscando por internet me topé con [pssh](https://linux.die.net/man/1/pssh), que puede ejecutar cosas en paralelo mediante SSH.

Pensándolo bien, fue bastante fácil ponerlo en marcha.

El problema era que, para ejecutar algunas cosas, necesitaba hacerlo con sudo. Pasar contraseñas de un lado a otro no era lo ideal, así que tuve que buscar de nuevo cómo enviar la contraseña de sudo cuando el servidor remoto la pidiera.

Resulta que es bastante fácil si das con el comentario de StackOverflow adecuado.

La versión resumida es:

stty -echo; printf "Password: "; read PASS; stty echo; echo "${PASS}" | \
pssh -h <HOSTFILE> -o /tmp/output -t 0 -I "`cat ./commands.sh`"

Hay que escribir -I "`cat ./commands.sh`" exactamente así (entre comillas y comillas invertidas); de lo contrario, no ejecuta bien los comandos. La contraseña se enviará como un comando aparte y no se tomará como entrada de sudo.

La otra trampa es que, por la manera en que está montado todo esto, hay que ejecutar sudo con el parámetro -S para que lea bien la contraseña.