views:

63

answers:

2

*Please do not pile on and tell me to just use SSH keys. If it bugs you that this is the way I am doing it, pretend that I am trying to telnet in instead. :-) *

I am using an expect script to run some routine commands on a set of servers under my control via ssh. The script should run set of commands (eg svn update ~/folderx\r") on each of the machines. My current script does everything I want it to do... sometimes. Other times it exits the ssh connection before it completes one of the last few commands.

Any thoughts on how I can make the connection stay until all of the commands are completed? The code below successfully logs on, successfully runs the first two commands or so (ap-get update and one of the svn updates) and then disconnects.

#!/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  A: 

Using Expect is generally the wrong way to do this kind of thing. The right way is to set up ssh keys so that you can ssh and run commands on the remote machine without supplying a password. Here's how to do that:

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

Here's a script that does the above in one fell swoop:

http://jakehofman.com/code/sshkey

You can then run commands on the remote machine like so:

ssh [email protected] ./foo args

To run commands on the remote machine with sudo, however, may be another story. Hopefully others can chime in about that. But as a first step you should avoid Expect for the initial login.

dreeves
Dang. I forgot to include in my initial question the preemptive "please don't tell me to just use ssh keys." :-)
vlasits
Ha, no problem. But now I'm curious, why not use ssh keys at least for the initial login?
dreeves
No reason at all. In fact, given that, I probably should have omitted the initial password/login lines in my snippet since that isn't really where the problem is occurring. In the interest of honesty I'll admit that I haven't tested it using keys, but I'm pretty sure that the problem I'm having would persist even if I did. Okay... you've talked me into it... I'll try it using keys.
vlasits
Thanks for your answer, Dan. It didn't solve the precise problem I was having (see below in my own answer to the question) but it did point me to a great script for ssh-keygen and reinforced a best practice I was neglecting.
vlasits
+1  A: 

It turns out that the reason it was exiting earlier was that the prompt pattern that I was matching against matched not only the prompt, but also some of the output from the svn commands I was running. I was matching against only the "username" portion of the prompt pattern (the prompt form was "username@machine:~$"). Once I altered the script to match only "username@" it began to work as expected.

p.s. the ssh script that dreeves links to above works very nicely.

vlasits