Controlling interactive programs with pexpect-u
A client I am working with requires that various machines have Ubuntu 10.04.4 installed along with certain software dependencies prior to installation of their own software.
In order to have our client avoid the tedious task of spinning up a new machine for each new client of theirs, I decided to attempt to automate the process (minus the OS installation) in Python.
A couple of the software installations require the user to interact with a console application. For example, this is the Matlab Runtime Environment installer:
and the Passenger installer:
Here I used the Python package pexpect-u which allows you to spawn child applications and control them automatically.
To spawn the Matlab installer I run:
import pexpect child = pexpect.spawn("sudo ./MCRInstaller.bin -console")
Now we tell pexpect what to expect:
child.expect("Press 1 for Next, 3 to Cancel or 5 to Redisplay \[1\]")
And we send a command with:
The package can be found here and the source code includes many more examples, one of which might be of use for this very client: hive.py
This client has various installations of a Rails application and each sends requests to the same location on a server. Because this location changes periodically, each of the Rails application installations need a configuration variable updated. I think the following should do the trick:
python hive.py user1:pass2@host1 user2:pass2@host2 ... userN:passN@hostN grep -rl 'old_location_path_string' /path/to/config/file | xargs sed -i 's/old_location_path_string/new_location_path_string/'
Let’s see it in action. I’ve set up two Ubuntu virtual machines and will be changing a string in a file that exists on both machines in the same location. First I login:
Let’s look at the contents of the files:
Now I’ll replace the string “Hello” with “Goodbye”:
Because the user of each machine has permissions over the test.conf file, I was able to modify it without sudo. If you’ll be needing to use sudo to make any changes, take a look at the :sync example here, however, note that if your sudo passwords differ on at least one of the remote machines this will not work.