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

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

Я использую сценарий ожидаемого запуска некоторых рутинных команд на наборе серверов под моим контролем через 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

2 ответа

Решение

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

ps ssh-скрипт, который снимает ссылки на вышеперечисленные, работает очень хорошо.

Использование 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 you@foo.com:.
2. Append that key to the authorized_keys file on the remote machine:
   % ssh you@foo.com '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 alice@remote.com ./foo args

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

Другие вопросы по тегам