使用Paramiko连接新EC2实例时遇到的问题

11 投票
5 回答
10471 浏览
提问于 2025-04-16 17:46

我正在写一个脚本,用来启动一个新的EC2实例,使用boto库,并通过Paramiko SSH客户端在这个实例上执行远程命令。不知道为什么,Paramiko客户端无法连接,我收到了这个错误:

Traceback (most recent call last):
  File "scripts/sconfigure.py", line 29, in <module>
    ssh.connect(instance.ip_address, username='ubuntu', key_filename=os.path.expanduser('~/.ssh/test'))
  File "build/bdist.macosx-10.3-fat/egg/paramiko/client.py", line 291, in connect
  File "<string>", line 1, in connect
socket.error: [Errno 61] Connection refused

我可以用相同的密钥文件和用户手动ssh连接,没问题。有没有人遇到过使用Paramiko的问题?我的完整代码在下面。谢谢。

import boto.ec2, time, paramiko, os
# Connect to the us-west-1 region
ec2 = boto.ec2.regions()[3].connect()
image_id = 'ami-ad7e2ee8'
image_name = 'Ubuntu 10.10 (Maverick Meerkat) 32-bit EBS'
new_reservation = ec2.run_instances(
    image_id=image_id,
    key_name='test',
    security_groups=['web'])

instance = new_reservation.instances[0]

print "Spinning up instance for '%s' - %s. Waiting for it to boot up." % (image_id, image_name)
while instance.state != 'running':
    print "."
    time.sleep(1)
    instance.update()

print "Instance is running, ip: %s" % instance.ip_address

print "Connecting to %s as user %s" % (instance.ip_address, 'ubuntu')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(instance.ip_address, username='ubuntu', key_filename=os.path.expanduser('~/.ssh/test'))
stdin, stdout, stderr = ssh.exec_command('echo "TEST"')
print stdout.readlines()
ssh.close()

5 个回答

2

为什么不直接使用 boto.manage.cmdshell 呢?

cmd = boto.manage.cmdshell.sshclient_from_instance(instance,
                                                   key_path,
                                                   user_name='ec2_user')

(这段代码来自于 ec2_launch_instance.py 的第152行)

想了解可用的 cmdshell 命令,可以查看 SSHClient 类,具体在 cmdshell.py 文件中。

3

检查SSH是否可用的方法是确保它的两个状态检查都通过。在网页界面上,它看起来是这样的:

这里输入图片描述

如果使用boto3(原来的问题是用boto,但那是五年前的事),我们可以这样做:

session = boto3.Session(...)
client = session.client('ec2')
res = client.run_instances(...) # launch instance
instance_id = res['Instances'][0]['InstanceId']

while True:
    statuses = client.describe_instance_status(InstanceIds=[instance_id])
    status = statuses['InstanceStatuses'][0]
    if status['InstanceStatus']['Status'] == 'ok' \
            and status['SystemStatus']['Status'] == 'ok':
        break
    print '.'
    time.sleep(5)
print "Instance is running, you are ready to ssh to it"
11

我好像通过反复尝试搞明白了这个问题。虽然根据boto的显示,实例状态是“运行中”,但实际上它会有一段时间才允许你通过SSH连接。为了避免这个问题,我在“ssh.connect(...)”之前加了一个“time.sleep(30)”,这样就能解决我的问题,不过这个时间可能因情况而异。

撰写回答