如何检查与AWS实例的SSH连接是否建立

9 投票
2 回答
7144 浏览
提问于 2025-04-17 19:55

我正在尝试通过 boto 连接到亚马逊的 EC2 实例,使用的是 SSH。因为我知道在实例创建后过一段时间才能建立 SSH 连接。所以我有几个问题:

  • 有没有办法检查实例上的 SSH 是否已经启动?(如果可以的话,怎么检查?)
  • 我该如何查看 boto.manage.cmdshell.sshclient_from_instance() 的输出?比如,如果输出显示 Could not establish SSH connection,那我该怎么再试一次。

这是我到目前为止尝试的,但没有成功:

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

当然,一切正常,因为我可以在过一段时间后再运行相同的代码,然后就能连接上,并且可以使用 cmd.shell()

2 个回答

1

我有两个部分,一个是用来检查这个实例是否在运行,另一个是用来检查这个实例是否可以访问。

# Get instance status till it is running
status_output=$(aws ec2 describe-instance-status --instance-ids $instance_id)
instance_status=$(jq -n "$status_output" | jq .InstanceStatuses[0] | jq .InstanceState.Name)
echo $instance_status
while [ ${instance_status:1:-1} != running ]
do
    status_output=$(aws ec2 describe-instance-status --instance-ids $instance_id)
    instance_status=$(jq -n "$status_output" | jq .InstanceStatuses[0] | jq .InstanceState.Name)
    echo $instance_status
done

# Get instance reachability till it is ready 
status_output=$(aws ec2 describe-instance-status --instance-ids $instance_id)
instance_reachability=$(jq -n "$status_output" | jq .InstanceStatuses[0] | jq .InstanceStatus.Status)
echo $instance_reachability
while [ ${instance_reachability:1:-1} != ok ]
do
    status_output=$(aws ec2 describe-instance-status --instance-ids $instance_id)
    instance_reachability=$(jq -n "$status_output" | jq .InstanceStatuses[0] | jq .InstanceStatus.Status)
    echo $instance_reachability
done
7

“SSH连接被拒绝,将在5秒后重试”的信息来自boto库:http://code.google.com/p/boto/source/browse/trunk/boto/manage/cmdshell.py

一开始,‘运行中’只是表示这个实例已经开始启动了。只要sshd(SSH守护进程)还没有启动,连接到22号端口的请求就会被拒绝。所以,如果在‘运行中’状态的前25秒内sshd没有启动,你看到的情况是完全正常的。

因为我们无法准确预测sshd什么时候会启动,如果你不想浪费时间去设定一个固定的长等待时间,你可以自己写一段代码,每隔1到5秒检查一下22号端口是否可以连接。只有在可以连接的时候,才调用boto.manage.cmdshell.sshclient_from_instance()

测试某个主机的特定TCP端口是否可达的一个简单方法是使用socket模块:

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()

撰写回答