Я создаю несколько виртуальных машин с помощью скрипта. В ходе этого я меняю имена виртуальных машин с помощью SSH. По какой-то причине, когда я запускаю следующую команду для трех виртуальных машин, она работает, а для магического числа при создании семи виртуальных машин SSH зависает. Может кто-нибудь объяснить это поведение?
часть скрипта. Этот скрипт выполняется одновременно для указанных X виртуальных машин.
...
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
...
незавершающиеся процессы ssh
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
я получил след на одном из запущенных процессов.
...
--- 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)
...
решение1
Это похоже на состояние гонки, и, глядя на ваш сценарий, я, кажется, понимаю, в чем дело.
Насколько я понимаю, у вас есть скрипт, содержащий следующие 2 строки (среди прочих):
ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts
И затем вы запускаете этот скрипт несколько раз.
Эта последовательность событий может объяснить вашу проблему:
- Один из скриптов открывается
~/.ssh/known_hosts
для выполненияssh-keygen -R
команды. В этот моментssh-keygen
команда считывает весь файл в память, чтобы удалить целевую строку. - Другой скрипт только что завершил выполнение
ssh-keyscan
и записал строку в файл. - Первый процесс скрипта
ssh-keygen
(тот, что из шага № 1) начинает записывать файл, но поскольку он прочитал файл до завершения шага № 2, файл, который он записывает, не содержит строку, добавленную шагом № 2. Поэтому строка из шага № 2 стирается. - Второй скрипт переходит к выполнению
ssh
, только ключ хоста отсутствуетknown_hosts
из-за проблемы, упомянутой в шаге № 3. Поэтому ssh зависает, требуя от пользователя подтверждения ключа.
Подробнее:
фоновые программы не могут читать с терминала, попытка сделать это приводит к тому, что эта программа получает SIGTTIN. Однако в вашем strace показано, что программа получает SIGTTOU. Обычно фоновые программы могут писать на терминал без проблем, однако OpenSSH явно включает параметр терминала, который называется , tostop
что приводит к такому поведению. Идя еще дальше, OpenSSH имеет обработчик сигналов для SIGTTOU (среди прочих), что приводит к тому, что код OpenSSH переходит в бесконечный цикл, пока вы не переведете процесс на передний план (в этот момент он может отобразить приглашение и прекратить получать сигнал).
Другой вопрос, как вы собираетесь решать эту проблему.
- Одним из решений было бы добавить блокировку (есть
flock
утилита, которую вы можете использовать) и заблокироватьknown_hosts
файл перед этими двумя строками, а затем разблокировать его после их завершения. - Другим решением было бы добавить опцию ssh
StrictHostKeyChecking=no
. Вы уже сводите на нет смысл файлаknown_hosts
этими двумя строками скрипта, так что вы могли бы просто отключить его вообще.