Использование 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 может быть другой историей. Надеюсь, другие могут вмешаться в это. Но в качестве первого шага вы должны избегать Ожидать первоначального входа в систему.