Использование Expect для администрирования машин через SSH, но не выполняет все задачи

*Пожалуйста, не нагромождайте и не говорите мне просто использовать SSH-ключи. Если вас раздражает, что я делаю это именно так, притворитесь, что вместо этого я пытаюсь подключиться через telnet. :-) *

Я использую сценарий ожидания для запуска некоторых рутинных команд на наборе серверов, находящихся под моим контролем, через ssh. Сценарий должен запускать набор команд (например, svn update ~/folderx\r") на каждой из машин. Мой текущий скрипт делает все, что я хочу, ... иногда. В других случаях он выходит из ssh-соединения до его завершения. из нескольких последних команд.

Любые мысли о том, как я могу сохранить соединение до тех пор, пока все команды не будут выполнены? Приведенный ниже код успешно входит в систему, успешно выполняет первые две команды или около того (обновление ap-get и одно из обновлений svn), а затем отключается.

#!/usr/bin/expect -f

spawn ssh username@ipaddress
set timeout -1
expect "Are you sure you want to continue connecting" {send "yes\r"; exp_continue} "password:" {send "*******\r"; exp_continue
    } "username@machine" {send "sudo apt-get update\r"}
expect "password" {send "*******\r"; exp_continue} "username@machine" {send "sudo svn update ~/folder1\r"}
expect "password" {send "*******\r"; exp_continue} "username@machine" {send "sudo svn update ~/folder2\r"}
expect "password" {send "*******\r"; exp_continue} "username@machine" {send "sudo svn update ~/folder3\r"}
expect "password" {send "*******\r"; exp_continue} "username@machine" {send "sudo reboot\r"}
close

person vlasits    schedule 12.07.2010    source источник
comment
не забудьте возврат каретки после send "yes"   -  person glenn jackman    schedule 13.07.2010


Ответы (2)


Использование Expect, как правило, является неправильным способом делать такие вещи. Правильный способ — настроить ключи ssh, чтобы вы могли использовать ssh и выполнять команды на удаленной машине без ввода пароля. Вот как это сделать:

0. Create public/private key pair on local machine.
   (Only needs to be done once on local machine for all remote machines.)
   Go to the ~/.ssh directory on your local machine and do this:
   % ssh-keygen -t rsa
1. Copy the public key to the remote machine:
   % scp ~/.ssh/id_rsa.pub [email protected]:.
2. Append that key to the authorized_keys file on the remote machine:
   % ssh [email protected] 'cat id_rsa.pub >> .ssh/authorized_keys; /bin/rm id_rsa.pub'
3. Finally, in case it doesn't work, check permissions, which must be just so: 
   (or maybe it's just that they can't be group/world writeable)
   % cd ~; ls -ld . .ssh .ssh/authorized_keys
     drwxr-xr-x  .
     drwxr-xr-x  .ssh
     -rw-r--r--  .ssh/authorized_keys

Вот скрипт, который делает все вышеперечисленное одним махом:

http://jakehofman.com/code/sshkey

Затем вы можете запускать команды на удаленной машине следующим образом:

ssh [email protected] ./foo args

Однако запуск команд на удаленной машине с помощью sudo может быть другой историей. Надеюсь, другие могут вмешаться по этому поводу. Но в качестве первого шага вам следует избегать ожидания при первоначальном входе в систему.

person dreeves    schedule 12.07.2010
comment
Данг. Я забыл включить в свой первоначальный вопрос превентивный вопрос, пожалуйста, не говорите мне просто использовать ключи ssh. :-) - person vlasits; 13.07.2010
comment
Ха, без проблем. Но теперь мне интересно, почему бы не использовать ключи ssh хотя бы для первоначального входа в систему? - person dreeves; 13.07.2010
comment
Нет причин вообще. На самом деле, учитывая это, мне, вероятно, следовало опустить начальные строки пароля/логина в моем фрагменте кода, так как на самом деле проблема возникает не там. Честно говоря, я признаю, что не проверял его с помощью ключей, но я почти уверен, что проблема, с которой я столкнулся, не исчезла бы, даже если бы я это сделал. Ладно... ты меня уговорил... Попробую с ключами. - person vlasits; 13.07.2010
comment
Спасибо за ответ, Дэн. Это не решило именно ту проблему, которая у меня была (см. Ниже мой собственный ответ на вопрос), но указало мне на отличный скрипт для ssh-keygen и укрепило передовую практику, которой я пренебрегал. - person vlasits; 14.07.2010

Оказывается, причина, по которой он завершался ранее, заключалась в том, что шаблон подсказки, с которым я сопоставлялся, соответствовал не только подсказке, но и некоторым выводам команд svn, которые я запускал. Я сопоставлял только часть шаблона подсказки «имя пользователя» (форма подсказки была «имя пользователя @ машина: ~ $»). Как только я изменил сценарий, чтобы он соответствовал только «username@», он начал работать, как и ожидалось.

p.s. ssh-скрипт, на который ссылаются выше, работает очень хорошо.

person vlasits    schedule 14.07.2010