estou criando alguns vms por meio de um script. como parte disso, estou alterando os nomes dos vms usando ssh. por algum motivo, quando executo o comando abaixo para três vms ele funciona e para o número mágico ao criar sete vms, o ssh trava. alguém pode explicar o comportamento?
parte do roteiro. este script é executado simultaneamente 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
...
processos ssh sem fim
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
eu descobri um dos processos em execução.
...
--- 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)
...
Responder1
Isso soa como uma condição de corrida e, olhando para o seu roteiro, acho que vejo onde.
Pelo que entendi, você tem um script que contém as 2 linhas a seguir (entre outras):
ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts
E você inicia esse script várias vezes.
Esta sequência de eventos pode explicar seu problema:
- Um dos scripts é aberto
~/.ssh/known_hosts
para executar ossh-keygen -R
comando. Neste ponto, ossh-keygen
comando lê todo o arquivo na memória para poder remover a linha de destino. - Outro script acabou de ser executado
ssh-keyscan
e gravou a linha no arquivo. - O primeiro
ssh-keygen
processo do script (aquele da etapa 1) começa a gravar o arquivo, mas como ele leu o arquivo antes da conclusão da etapa 2, o arquivo que está gravando não contém a linha adicionada pela etapa 2. Portanto, a linha da etapa 2 é apagada. - O segundo script executa o
ssh
, apenas a chave do host não está inseridaknown_hosts
devido ao problema mencionado na etapa 3. Então o ssh trava querendo que o usuário confirme a chave.
Mais detalhes:
Os programas em segundo plano não podem ler do terminal, tentar fazer isso resulta no envio de um SIGTTIN para esse programa. Porém no seu strace, mostra o programa recebendo um SIGTTOU. Normalmente, os programas em segundo plano podem gravar no terminal sem problemas, no entanto, o OpenSSH ativa explicitamente uma configuração de terminal chamada tostop
que resulta nesse comportamento. Indo ainda mais longe, o OpenSSH possui um manipulador de sinal no SIGTTOU (entre outros) que faz com que o código OpenSSH entre em um loop infinito até que você traga o processo para o primeiro plano (ponto em que ele pode exibir o prompt e parar de ser sinalizado).
Como você deseja resolver isso é outra questão.
- Uma solução seria adicionar bloqueio (existe um
flock
utilitário que você pode usar) e bloquear oknown_hosts
arquivo antes dessas duas linhas e desbloquear depois de terminar. - Outra solução seria adicionar a opção ssh
StrictHostKeyChecking=no
. Você já está anulando o propósito doknown_hosts
arquivo com essas duas linhas do script, então é melhor desativá-lo completamente.