Search This Blog

Friday, August 21, 2009

Expect and operation on many computers

Recently, I had to delete a directory on around 200 computers. The directory belonged to root, so using my account with public key authentication wasn't possible. I googled a bit, found the expect and wrote the following script.
#!/usr/bin/expect -f

set machine [lindex $argv 0]
set command [lindex $argv 1]
set timeout -1
spawn ssh -l root $machine $command
match_max 100000

expect "?*assword: $"
send "password\n"

expect eof
The script sets the name of a remote machine (set machine [lindex $argv 0]) and a command (set command [lindex $argv 1]) to execute from arguments it is started with. Next tries to connect to the remote machine (spawn ssh -l root $machine $command) and when it's asked for the password (expect "?*assword: $") send it (send "password\n"). Of course you have to change the password to the root password. Finally, it waits for the EOF from ssh (expect eof). I have confess that I don't remember what exactly set timeout -1 and match_max 100000 means ;) The script can be called with loop similar to one below.
for cell in 1{0..3}{0..9} ;\
do for box in {1..4} ;\
do echo  c${bc}-box0${app} ; \
./command.script bc${bc}app-0${app} "ls /var/log/httpd" ; \
done; \
done
One more thing. The script assumes that you has connected at least one to all machines or rather that the machines has been added to your .ssh/know_hosts file. If you plan to use script to initialize the first connection you should add following line
expect "Are you sure you want to continue connecting (yes/no)?"
send "yes\n"
before the line expect "?*assword: $", but in such case all machine haven't to be present in .ssh/know_hosts file.

2 comments:

rozie said...

Works only if you have the same password on all machines, and login directly to root account permited, right? Another useful solution for this may be clusterssh. And running puppet or cfengine as ultimate solution.

Wawrzek said...

I would like to agree with rozie.

His comment has helped me to develop another solution. This one required having user account with sudo on all machines.

Doing in the loop ssh $machine sudo $command should work, with remote access to root acount, but in such case script needs expect to feed sudo password.

BTW. We are using puppet, but this was a file not controlled by it.