suspendendo processos ssh iniciados a partir de um script

3

Estou criando alguns vms através de um script. como parte disso, estou mudando os nomes do vms usando ssh. Por alguma razão, quando eu executar o comando abaixo para três vms 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 especificado.

...
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 não finais

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 tenho um passo em frente no processo de 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)
...
    
por rag 06.10.2013 / 02:23

1 resposta

2

Isso soa como uma condição de corrida, e olhando para o seu script, eu acho que vejo onde.

Pelo que entendi, você tem um script que contém as duas linhas seguintes (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 o seu problema:

  1. Um dos scripts abre ~/.ssh/known_hosts para pré-forma o comando ssh-keygen -R . Neste ponto, o comando ssh-keygen tem o arquivo inteiro lido na memória para que possa remover a linha de destino.
  2. Outro script acabou de executar ssh-keyscan e de gravar a linha no arquivo.
  3. O processo ssh-keygen do primeiro script (aquele do passo 1) começa a escrever o arquivo, mas como ele leu o arquivo antes da conclusão da etapa 2, o arquivo que está sendo escrito não contém a linha descrita 2 adicionado. Então a linha da etapa 2 é apagada.
  4. O segundo script serve para executar o ssh , somente a chave do host não está em known_hosts devido ao problema mencionado na etapa nº 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 a partir do terminal, ao tentar fazer isso, os resultados nesse programa são enviados com um SIGTTIN. No entanto, no seu strace, ele 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 definição de terminal chamada tostop , que resulta nesse comportamento. Indo ainda mais longe, o OpenSSH tem um manipulador de sinal no SIGTTOU (entre outros) que resulta no código OpenSSH entrando em um loop infinito até que você leve o processo para o forground (no ponto em que ele pode exibir o prompt e parar de ser sinalizado).

Como você quer resolver isso é outra questão.

  • Uma solução seria adicionar bloqueio (há um utilitário flock que você pode usar) e bloquear o arquivo known_hosts antes dessas duas linhas e, em seguida, desbloquear depois que elas forem concluídas.
  • Outra solução seria adicionar a opção ssh StrictHostKeyChecking=no . Você já está derrotando a finalidade do arquivo known_hosts com essas duas linhas do script, então é melhor desativá-lo.
por 06.10.2013 / 07:51