Issue
I'm trying to connect to the Amazon EC2 instance via SSH using boto
. I know that ssh connection can be established after some time after instance was created. So my questions are:
- Can I somehow check if SSH is up on the instance? (if so, how?)
- Or how can I check for the output of
boto.manage.cmdshell.sshclient_from_instance()
? I mean for example if the output prints outCould not establish SSH connection
, than try again.
That's what I tried so far, but have no luck:
if instance.state == 'running':
retry = True
while retry:
try:
print 'Connecting to ssh'
key_path = os.path.join(os.path.expanduser('~/.ssh'), 'secret_key.pem')
cmd = boto.manage.cmdshell.sshclient_from_instance(instance,
key_path,
user_name='ec2-user')
print instance.update()
if cmd:
retry = False
except:
print 'Going to sleep'
time.sleep(10)
SSH Connection refused, will retry in 5 seconds
SSH Connection refused, will retry in 5 seconds
SSH Connection refused, will retry in 5 seconds
SSH Connection refused, will retry in 5 seconds
SSH Connection refused, will retry in 5 seconds
Could not establish SSH connection
And of course everything is working properly, because I can launch the same code after some time and will get a connection, and will be able to use cmd.shell()
Solution
The message "SSH Connection refused, will retry in 5 seconds" is coming from boto: http://code.google.com/p/boto/source/browse/trunk/boto/manage/cmdshell.py
Initially, 'running' just implicates that the instance has started booting. As long as sshd
is not up, connections to port 22 are refused. Hence, what you observe is absolutely to be expected if sshd
does not come up within the first 25 seconds of 'running' state.
Since it is not predictable when sshd
comes up exactly and in case you do not want to waste time by just defining a constant long waiting period, you could implement your own polling code that in e.g. 1 to 5 second intervals checks if port 22 is reachable. Only if it is invoke boto.manage.cmdshell.sshclient_from_instance()
.
A simple way to test if a certain TCP port of a certain host is reachable is via the socket
module:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(('hostname', 22))
print "Port 22 reachable"
except socket.error as e:
print "Error on connect: %s" % e
s.close()
Answered By - Dr. Jan-Philip Gehrcke