尝试使用 Paramiko 通过 SSH 连接到新的 EC2 实例时出现问题

发布于 2024-11-08 11:13:58 字数 1531 浏览 4 评论 0 原文

我正在编写一个脚本,该脚本使用 boto 启动一个新的 EC2 实例,并使用 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()

I'm working on a script that spins up a fresh EC2 instance with boto and uses the Paramiko SSH client to execute remote commands on the instance. For whatever reason, the Paramiko client is unabled to connect, I get the error:

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

I can ssh in fine manually using the same key file and user. Has anyone run into issues using Paramiko? My full code is below. Thanks.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

望喜 2024-11-15 11:13:58

我似乎已经通过反复试验弄清楚了这一点。尽管根据 boto 的说法,实例状态为“正在运行”,但实际允许 SSH 连接时仍存在延迟。在“ssh.connect(...)”之前添加“time.sleep(30)”似乎对我有用,尽管这可能会有所不同。

I seem to have figured this out by trial and error. Even though the instance status is "running" according to boto, there is a delay for when it will actually allow an SSH connection. Adding a "time.sleep(30)" before the "ssh.connect(...)" seems to do the trick for me, though this may vary.

南风起 2024-11-15 11:13:58

检查 ssh 是否可用的方法是确保其两次状态检查均通过。在网络用户界面上它看起来像这样:
输入图片这里的描述

使用boto3(最初的问题使用boto,但那是5年前的事了),我们可以这样做:

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"

The way to check it's ssh available is to make sure its two status checks both passes. On web UI it looks like this:
enter image description here

And using boto3 (the original question used boto but it was 5 years ago), we can do:

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"
审判长 2024-11-15 11:13:58

为什么不使用 boto.manage.cmdshell 来代替?

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

ec2_launch_instance.py 中的第 152 行)

(代码取自 >cmdshell 命令查看 SSHClient 类href="https://github.com/boto/boto/blob/master/boto/manage/cmdshell.py" rel="nofollow">cmdshell.py

Why not use boto.manage.cmdshell instead?

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

(code taken from line 152 in ec2_launch_instance.py)

For available cmdshell commands have a look at the SSHClient class from cmdshell.py.

我的奇迹 2024-11-15 11:13:58

我最近遇到了这个问题。 “正确”的方法是首先启动 close() 然后重新打开连接。然而在旧版本中, close() 被破坏了。

在此版本或更高版本中,应该修复该问题:
https://github.com/boto/boto/pull/412

“正确”方法:

newinstance = image.run(min_count=instancenum, max_count=instancenum, key_name=keypair, security_groups=security_group, user_data=instancename, instance_type=instancetype, placement=zone)
time.sleep(2)
newinstance.instances[0].add_tag('Name',instancename)

print "Waiting for public_dns_name..."
counter = 0
while counter < 70:
    time.sleep(1)
    conn.close()
    conn = boto.ec2.connection.EC2Connection(ec2auth.access_key,ec2auth.private_key)
    startedinstance = conn.get_all_instances(instance_ids=str(newinstance.instances[0].id))[0]
    counter = counter + 1
    if str(startedinstance.instances[0].state) == "running":
        break
    if counter == 69:
        print "Timed out waiting for instance to start."
print "Added: " + startedinstance.instances[0].tags['Name'] + " " + startedinstance.instances[0].public_dns_name

I recently ran into this issue. The "correct" way would be to initiate a close() first and then reopen the connection. However on older versions, close() was broken.

With this version or later, it should be fixed:
https://github.com/boto/boto/pull/412

"Proper" method:

newinstance = image.run(min_count=instancenum, max_count=instancenum, key_name=keypair, security_groups=security_group, user_data=instancename, instance_type=instancetype, placement=zone)
time.sleep(2)
newinstance.instances[0].add_tag('Name',instancename)

print "Waiting for public_dns_name..."
counter = 0
while counter < 70:
    time.sleep(1)
    conn.close()
    conn = boto.ec2.connection.EC2Connection(ec2auth.access_key,ec2auth.private_key)
    startedinstance = conn.get_all_instances(instance_ids=str(newinstance.instances[0].id))[0]
    counter = counter + 1
    if str(startedinstance.instances[0].state) == "running":
        break
    if counter == 69:
        print "Timed out waiting for instance to start."
print "Added: " + startedinstance.instances[0].tags['Name'] + " " + startedinstance.instances[0].public_dns_name
菊凝晚露 2024-11-15 11:13:58

我最近查看了这段代码,并对代码提出了建议,
您可以尝试“wait_until_running()”,而不是运行 while 循环来检查实例是否正在运行。

以下是示例代码...

client = boto3.resource(
    'ec2',
    region_name="us-east-1"
)

Instance_ID = "<your Instance_ID>"
instance = client.Instance(Instance_ID)
instance.start()
instance.wait_until_running()

之后尝试编写 ssh 连接代码。

I recently view this code and I have a suggestion for code,
Instead of running while loop to check whether the instance is running or not, you can try "wait_until_running()".

Following is the sample code...

client = boto3.resource(
    'ec2',
    region_name="us-east-1"
)

Instance_ID = "<your Instance_ID>"
instance = client.Instance(Instance_ID)
instance.start()
instance.wait_until_running()

After that try to code for the ssh connection code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文