I’ve been playing with Amazon EC2 recently. It’s pretty cool. It solves problems such as ‘I want to run Windows to test some stuff, what do I do?’ and ‘I need a calcserver to run whilst I’m working on my eeepc on the road, what do I do?’.
The cost per hour is pretty low, but if you leave an instance up for a few days or months, the charges will start to rack up.
If I was running off a desktop in my own house, I might create a screensaver that automatically shuts down the instances when it kicks in. Screensaver running: instances down. Screensaver not running: who knows?
But I’m not. I’m on an eeepc, in various Starbucks and so on, which is fairly comfortable, but raises the questions:
- what do I do if I start an instance and the network goes down? I can’t stop it any more!
- how to make sure that when I close the netbook – putting it to sleep straight away – the instances die?
My original solution was to make the instances themselves shut themselves down after an hour. It works, but:
- it means modifying the images, and storing them somewhere -> lots of work, you have to pay for storage space, and what if I forget, or there is a bug, or I don’t install it to the machine correctly?
- sometimes I don’t want them to shut down once an hour
My latest solution is to create a cron task on my web hosting, which shuts down my EC2 instances if I don’t have an ssh connection to the hosting.
Then, when I turn off my netbook / put it on stand-by, the ssh connection to my hosting will die, the cron job will kick in and the instances are guaranteed to die (guaranteed in the loosest sense of hte term of course….). It even sends me a nice email about it!
How does this work? There are three parts:
- cron configuration itself
- script which detects whether I’m logged in on a bash session
- script which shuts down the instances, and emails me about it
Cron configuration. Type ‘crontab -e’, and add a line like:
33 * * * * /home/youruseraccount/ac/terminateinstancesifnoconnections.sh
This will run the script at 33 minutes past the hour, every hour, forever.
For testing, you can change the 33 to *, which will make it run once a minute. Be careful, you can flood your email system, and use up lots of webhosting cpu
Next, the script that cron runs is:
#!/bin/bash
scriptdir=$(dirname $0)
psnum=$(ps -ef|grep 'b[a]sh' | wc -l)
if [[ $psnum != 2 ]]; then {
# echo 'other connections present'>&2
exit 0;
} fi
bash $scriptdir/terminateinstances.sh
Make sure it is executable (chmod +x), and is found at the location you gave to crontab earlier.
What is ‘grep ‘b[a]sh’? This came up in an interview I went to last week, and I just figured out the answer whilst writing this script! Basically it matches ‘bash’ but it doesn’t match ‘grep ‘b[a]sh’, ie it doesn’t match itself! which is neat.
The script looks for other instances of bash. The $() is one instance. The script itself is another, when run from cron. So that would be 2. If there are not 2, then I’m already connected to bash on an ssh session most likely. If it’s another cron job, it’s not a biggie, it’ll kick in again an hour later, unless every cron job is configured for 33 minutes past the hour I guess
And finally, a script to terminate the instances and mail me:
#!/bin/bash
. $HOME/.bash_profile
instances=$(ec2-describe-instances | grep INSTANCE | awk '{print $2,$4}' | grep -v terminated | awk '{print $1}')
for instance in $instances; do {
echo terminating instance $instance >&2
ec2-terminate-instances $instance
} done
This assumes that $HOME/.bash_profile contains the environment setup for amazon EC2, ie EC2_HOME, JAVA_HOME, etc
What the script does is use ec2-describe-instances to get a list of instances, grep for all that don’t have a status of ‘terminated’, and then run a for loop calling ec2-terminate-instances for each one.
What about the email? Well, when you create a script in cron, anything you redirect to stderr, ie ‘>&2′ gets added to an email, and sent to you! If there is nothing, then no email, otherwise it all get concatenated together, and emailed to you at the end of the job.
So we can an email if and only if an instance is detected as not terminated and is terminated.
The crontab line makes it run once an hour, so if the ssh connection to the webhosting dies occasioanally, it’s not a biggy, it won’t instantly kill hte instances, but it makes sure they’re not going to run all night, or month, or decade…