如何使用 boto3 在 EC2 中 SSH 和运行命令?

Posted

技术标签:

【中文标题】如何使用 boto3 在 EC2 中 SSH 和运行命令?【英文标题】:How to SSH and run commands in EC2 using boto3? 【发布时间】:2017-07-27 11:28:27 【问题描述】:

我希望能够通过 ssh 进入 EC2 实例,并在其中运行一些 shell 命令,例如 this。

如何在 boto3 中做到这一点?

【问题讨论】:

相关:Boto Execute shell command on ec2 instance "client.exec_command()"和"client.send_command()"有什么区别? 【参考方案1】:

你不会从 python SSH。您可以使用boto3 模块与EC2 实例进行交互。

Here 你有一个完整的boto3 文档以及你可以使用它运行哪些命令。

【讨论】:

但是,使用boto,可以通过 ssh 进入实例,对吗?那么,是否意味着特定模块没有迁移到 boto3 中? 您不会通过 SSH 访问实例。您只需连接到 EC2 服务,然后您就可以启动/停止并与不同的实例进行交互,但不能通过 SSH 连接到它们。为此,您根本不需要boto3。您可以简单地从终端进行 SSH。如果您仍想通过 SSH 使用 python 执行命令,可以查看this 问题。【参考方案2】:

Boto 提供了一种使用 Paramiko 以编程方式通过 SSH 连接到 EC2 实例然后运行命令的方法。 Boto3 不包含此功能。您可以修改 boto 代码以使用 boto3 而不需要大量的努力。或者您可以考虑使用类似 fabric 或 ansible 的东西,它们提供了一种更强大的方式来远程在 EC2 实例上执行命令。

【讨论】:

Boto3 删除了该功能,因为它不再需要它来实现 OP 的目标 - 通过 AWS 的 Run Command 系统。请参阅我的答案以获取示例:)【参考方案3】:

您可以使用以下代码 sn-p ssh 到 EC2 实例并从 boto3 运行一些命令。

import boto3
import botocore
import paramiko

key = paramiko.RSAKey.from_private_key_file(path/to/mykey.pem)
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# Connect/ssh to an instance
try:
    # Here 'ubuntu' is user name and 'instance_ip' is public IP of EC2
    client.connect(hostname=instance_ip, username="ubuntu", pkey=key)

    # Execute a command(cmd) after connecting/ssh to an instance
    stdin, stdout, stderr = client.exec_command(cmd)
    print stdout.read()

    # close the client connection once the job is done
    client.close()
    break

except Exception, e:
    print e

【讨论】:

是的,就是这样。 Boto3 没有 ssh。似乎已放弃使用 EC2 Run Command。您可以使用它来触发命令。不过坦率地说,这有点痛苦。 sshclient 工作正常。但是,当运行特定于 awscli 的命令时,它会失败并出现错误,即使已经安装了 'aws' 也找不到 @AnandhuAjayakumar:docs.aws.amazon.com/cli/latest/userguide/troubleshooting.html 应该会帮助你! 这段代码中有import boto3import botocore的理由吗? 我得到了一个 AttributeError: 'NoneType' object has no attribute 'time' paramiko 错误,这个问题在 exec_command 调用后通过 time.sleep(5) 解决了这个问题:***.com/questions/60037299/… - 否则这个很好用,谢谢【参考方案4】:

这个帖子有点老了,但由于我花了一个令人沮丧的下午发现一个简单的解决方案,我不妨分享一下。

NB 这不是对 OP 问题的严格回答,因为它不使用 ssh。但是,boto3 的一点是您不必这样做 - 所以我认为在大多数情况下,这将是实现 OP 目标的首选方式,因为他/她可以轻松地使用他/她现有的 boto3 配置。

AWS 的运行命令内置于 botocore 中(因此据我所知,这应该适用于 boto 和 boto3)但免责声明:我只使用 boto3 进行了测试

def execute_commands_on_linux_instances(client, commands, instance_ids):
    """Runs commands on remote linux instances
    :param client: a boto/boto3 ssm client
    :param commands: a list of strings, each one a command to execute on the instances
    :param instance_ids: a list of instance_id strings, of the instances on which to execute the command
    :return: the response from the send_command function (check the boto3 docs for ssm client.send_command() )
    """

    resp = client.send_command(
        DocumentName="AWS-RunShellScript", # One of AWS' preconfigured documents
        Parameters='commands': commands,
        InstanceIds=instance_ids,
    )
    return resp

# Example use:
ssm_client = boto3.client('ssm') # Need your credentials here
commands = ['echo "hello world"']
instance_ids = ['an_instance_id_string']
execute_commands_on_linux_instances(ssm_client, commands, instance_ids)

对于 Windows 实例 powershell 命令,您可以使用替代选项:

        DocumentName="AWS-RunPowerShellScript",

【讨论】:

使用正确的实例 id 时,我仍然收到客户端错误:ClientError:调用 SendCommand 操作时发生错误 (InvalidInstanceId):我该怎么办?请帮助我,谢谢。 嗨,Beatrice,这很可能发生在实例 id 给出不正确的情况下(它需要是字符串列表,如上面给出的示例中所示 [通过执行 print(instance_ids) 进行检查]或者您提供的实例 ID 与正在运行的机器实例不对应[登录到您的 AWS 控制台以检查您指定的机器实例是否实际运行]。如果这些检查失败,我建议发布一个新的 SO问题:) 看起来错误实际上是由于 IAM 权限。我用 paramiko 代替它。感谢您的回复。!​​ 另一个需要注意的是,需要安装最新的 AWS SSM 代理,并且运行实例的 IAM 角色具有适当的权限(将 AmazonEC2RoleforSSM 策略添加到角色)【参考方案5】:

使用 boto3 发现实例并使用 fabric 在实例上运行命令

【讨论】:

【参考方案6】:

这是我的做法

import boto3
import botocore
import boto
import paramiko

ec2 = boto3.resource('ec2')

instances = ec2.instances.filter(
    Filters=['Name': 'instance-state-name', 'Values': ['running']])
i = 0
for instance in instances:
    print(instance.id, instance.instance_type)
    i+= 1
x = int(input("Enter your choice: "))
try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    privkey = paramiko.RSAKey.from_private_key_file('address to .pem key')
    ssh.connect(instance.public_dns_name,username='ec2-user',pkey=privkey)
    stdin, stdout, stderr = ssh.exec_command('python input_x.py')
    stdin.flush()
    data = stdout.read().splitlines()
    for line in data:
        x = line.decode()
        #print(line.decode())
        print(x,i)
        ssh.close()

对于credentails,我已经添加了AWSCLI包,然后在终端运行

aws configure

输入凭据。它们都将保存在 .aws 文件夹中,您也可以更改路径。

【讨论】:

【参考方案7】:

您也可以使用kittenpython 库来实现它,它只是对 boto3 的封装。您还可以使用此实用程序同时在多台服务器上运行相同的命令。

例如。

kitten run uptime ubuntu 18.105.107.20

【讨论】:

以上是关于如何使用 boto3 在 EC2 中 SSH 和运行命令?的主要内容,如果未能解决你的问题,请参考以下文章

在 Boto3 中获取具有特定标签和值的 EC2 实例列表

我们如何使用 python boto3 获取挂载到 EC2 实例的所有文件系统(EFS)的列表?

boto3如何获取单个ec2实例的所有标签并附加新标签

如何使用 boto3 指定 core-os ec2 实例的根卷大小?

如何使用 boto3 从连接到 ECS 任务的网络接口获取公共 IP

使用 Boto 3 显示 EC2 实例名称