Estoy creando algunas máquinas virtuales mediante un script. Como parte de esto, estoy cambiando los nombres de las máquinas virtuales usando ssh. Por alguna razón, cuando ejecuto el siguiente comando para tres máquinas virtuales, funciona y para el número mágico al crear siete máquinas virtuales, el ssh se bloquea. ¿Alguien puede explicar el comportamiento?
parte del guión. Este script se ejecuta simultáneamente para X vms especificados.
...
ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts
SSH="ssh -i $SSH_KEY -o PasswordAuthentication=no"
echo "hostname $hostname &&
echo HOSTNAME=$hostname >> /etc/sysconfig/network &&
echo 127.0.0.1 $hostname >> /etc/hosts " | ssh -i $SSH_KEY -o PasswordAuthentication=no root@IP
...
procesos ssh sin fin
rag 2867 2808 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm4
rag 2869 2812 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm7
rag 2872 2818 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm1
rag 2875 2811 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm6
rag 2879 2814 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm5
rag 2881 2813 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm3
rag 2884 2807 0 01:05 pts/5 T 00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm2
Tengo rastro de uno de los procesos en ejecución.
...
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
rt_sigreturn(0x16) = -1 EINTR (Interrupted system call)
rt_sigaction(SIGALRM, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTSTP, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTTIN, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTTOU, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
close(4) = 0
kill(2867, SIGTTOU) = 0
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
open("/dev/tty", O_RDWR) = 4
rt_sigaction(SIGALRM, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGHUP, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGINT, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGPIPE, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGQUIT, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTERM, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTSTP, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTTIN, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTTOU, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_CONTINUE or TCSETSF, {B38400 opost isig icanon echo ...}) = ? ERESTARTSYS (To be restarted)
...
Respuesta1
Esto suena como una condición de carrera y, al mirar tu guión, creo que veo dónde.
Según tengo entendido, tiene un script que contiene las siguientes 2 líneas (entre otras):
ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts
Y luego inicias ese script varias veces.
Esta secuencia de eventos puede explicar su problema:
- Uno de los scripts se abre
~/.ssh/known_hosts
para ejecutar elssh-keygen -R
comando. En este punto, elssh-keygen
comando lee todo el archivo en la memoria para poder eliminar la línea de destino. - Otro script acaba de terminar de ejecutarse
ssh-keyscan
y escribir la línea en el archivo. - El proceso del primer script
ssh-keygen
(el del paso 1) comienza a escribir el archivo, pero debido a que leyó el archivo antes de que finalizara el paso 2, el archivo que está escribiendo no contiene la línea que agregó el paso 2. Entonces la línea del paso 2 se borra. - El segundo script realiza la ejecución
ssh
, solo que la clave de host no estáknown_hosts
debido al problema mencionado en el paso 3. Entonces ssh se cuelga y quiere que el usuario confirme la clave.
Más detalles:
los programas en segundo plano no pueden leer desde la terminal; al intentar hacerlo, se envía a ese programa un SIGTTIN. Sin embargo, en su ruta, muestra que el programa obtiene un SIGTTOU. Normalmente, los programas en segundo plano pueden escribir en la terminal sin problemas; sin embargo, OpenSSH activa explícitamente una configuración de terminal llamada tostop
que da como resultado este comportamiento. Yendo aún más lejos, OpenSSH tiene un controlador de señales en SIGTTOU (entre otros) que hace que el código OpenSSH entre en un bucle infinito hasta que usted pone el proceso en primer plano (en cuyo momento puede mostrar el mensaje y dejar de recibir señales).
Cómo quieres resolver esto es otra cuestión.
- Una solución sería agregar bloqueo (hay una
flock
utilidad que puede usar) y bloquear elknown_hosts
archivo antes de esas 2 líneas, y luego desbloquearlo una vez que hayan terminado. - Otra solución sería agregar la opción ssh
StrictHostKeyChecking=no
. Ya estás frustrando el propósito delknown_hosts
archivo con esas 2 líneas del script, por lo que también puedes desactivarlo por completo.