SSH hace que el ciclo se detenga

30

Finalmente he logrado reducir un problema con el que he estado luchando durante algunas semanas. Utilizo SSH con "claves autorizadas" para ejecutar comandos de forma remota. Todo está bien, excepto cuando lo hago en un ciclo while. El ciclo termina después de completar cualquier iteración con un comando ssh.

Durante mucho tiempo pensé que esto era una especie de rareza ksh, pero ahora descubrí que bash se comporta de manera idéntica.

Un pequeño programa de muestra para reproducir el problema. Esto se destila de una implementación más grande que toma instantáneas y las replica entre los nodos en un clúster.

#!/bin/bash

set -x

IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool

ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG    " > /tmp/actionlist

#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
   echo ${RMT_FILESYSTEM}@${MARKER}
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?
done

(Tenga en cuenta que hay un carácter TAB en la expresión de búsqueda grep según la definición del comportamiento de la opción zfs list "-H").

Mi muestra tiene algunos sistemas de archivos ZFS para la raíz donde todas las "zonas" tienen su sistema de archivos raíz en un conjunto de datos llamado similar a

POOL / zones / app1zone
POOL / zones / group2 / app2zone

etc.

El bucle anterior debe crear una instantánea para cada uno de los conjuntos de datos seleccionados, pero en su lugar opera solo en el primero y luego sale.

Se puede confirmar fácilmente que el programa encuentra el número correcto de conjuntos de datos al verificar el archivo "/ tmp / actionlist" después de que exista el script.

Si el comando ssh es reemplazado por, por ejemplo, un comando echo, entonces el ciclo itera a través de todas las líneas de entrada. O mi favorito: anteponer "echo" al comando ofensivo.

Si uso un bucle for en su lugar, también funciona, pero debido al tamaño potencial de la lista de conjuntos de datos, esto podría causar problemas con la longitud máxima de la línea de comandos expandida.

¡Ahora estoy 99.999% seguro de que solo los bucles con comandos ssh me dan problemas!

Tenga en cuenta que la iteración en la que se ejecuta el comando ssh se completa. Es como si los datos introducidos en el bucle while se perdieran repentinamente ... Si las primeras líneas de entrada no ejecutan un comando ssh, el bucle continúa hasta que realmente ejecuta el comando SSH.

En mi computadora portátil donde estoy probando esto, tengo dos máquinas virtuales Solaris 10 con solo unos dos o tres conjuntos de datos de muestra, pero lo mismo está sucediendo en los grandes sistemas SPARC en los que está destinado a funcionar, y hay muchos conjuntos de datos.

Johan
fuente
77
SSH podría estar leyendo de la entrada estándar, comiendo tu actionlist. Intente redirigir la entrada estándar de ssh a/dev/null
BatchyX
Probaré eso. Quiero agregar que poner ssh en un contenedor no ayuda ...
Johan
Estás en lo correcto. ¿Cómo podría no ver eso?
Johan
@BatchyX Creo que tu comentario califica como una respuesta.
un CVn
Estoy de acuerdo en que me gustaría "aceptar" la respuesta, así que si @BatchyX podría volver a publicarla como tal, lo haré.
Johan

Respuestas:

43

SSH podría estar leyendo de la entrada estándar, consumiendo su lista de acciones. Intente redirigir la entrada estándar de ssh a / dev / null:

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null

Como regla general, cuando ejecuto comandos que pueden interferir con la entrada estándar bajo un while readbucle de estilo, me gusta envolver todo el cuerpo del bucle entre llaves:

cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
    echo ${RMT_FILESYSTEM}@${MARKER}
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done
BatchyX
fuente
3
Doble asombroso para el uso específico de las llaves ... que he encontrado en 20 años de secuencias de comandos que nunca encontré (al menos no que yo pueda recordar). Y para la inferencia uuoc. FWIW (y en mi propia defensa) ¡A veces hago una excepción y agrego declaraciones de gato redundantes por razones de legibilidad! Me encanta este foro porque de repente estoy aprendiendo cosas nuevas nuevamente Específicamente, me gusta agregar redireccionamientos al inicio de líneas como este caso, pero en foros que parecen confundir el asunto, ¡me hacen obtener menos respuestas útiles!
Johan
He estado tratando de resolver la diferencia entre {...} y (...) la página de manual de ksh dice que {...} son palabras clave especiales reconocidas solo al comienzo de una línea de comando. Pero hay otra diferencia ... ( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )difiere igual con las llaves. Me refiero a la producción producida, no al hecho de que la llave de cierre debe estar en una nueva línea ...
Johan
55
Además, ssh de OpenSSH tiene la -nopción que hace que (efectivamente) vuelva a abrir su stdin desde / dev / null.
Chris Johnsen
¿Alguna solución para usar sudocon el comando dentro del bucle?
bonh
Solía ​​usar -n desde hace años y en algún momento perdí el hábito ... y ahora sé de nuevo por qué lo hice, después de pasar un tiempo cavando ...
Florian Heigl