如何通过boto3在EC2实例上运行Python脚本

3

我之前看过这个问题的提问:如何使用boto3在EC2上进行SSH并运行命令?很多答案都说用户不必使用ssh连接到EC2并运行命令。然而,我还是不知道如何通过boto3运行python脚本。在boto2中,有一个名为run_instances的函数,用户可以将他们的脚本传递到EC2节点并运行它,就像下面的代码列表一样。

def run(self, **kwargs):
    ec2 = boto.connect_ec2(settings.PDF_AWS_KEY, settings.PDF_AWS_SECRET)
    sqs = boto.connect_sqs(settings.PDF_AWS_KEY, settings.PDF_AWS_SECRET)

    queue = sqs.create_queue(REQUEST_QUEUE)
    num = queue.count()
    launched = 0
    icount = 0

    reservations = ec2.get_all_instances()
    for reservation in reservations:
        for instance in reservation.instances:
            if instance.state == "running" and instance.image_id == AMI_ID:
                icount += 1
    to_boot = min(num - icount, MAX_INSTANCES)

    if to_boot > 0:
        startup = BOOTSTRAP_SCRIPT % {
            'KEY': settings.PDF_AWS_KEY,
            'SECRET': settings.PDF_AWS_SECRET,
            'RESPONSE_QUEUE': RESPONSE_QUEUE,
            'REQUEST_QUEUE': REQUEST_QUEUE}
        r = ec2.run_instances(
            image_id=AMI_ID,
            min_count=to_boot,
            max_count=to_boot,
            key_name=KEYPAIR,
            security_groups=SECURITY_GROUPS,
            user_data=startup)
        launched = len(r.instances)
    return launched

BOOTSTRAP_SCRIPT是一个Python脚本。

我使用boto3编写了一些代码:

# -*- coding: utf-8 -*-

SCRIPT_TORUN = """

import boto3

bucket = random_str()
image_name = random_str()
s3 = boto3.client('s3')
Somedata = 'hello,update'

upload_path = 'test/' + image_name
s3.put_object(Body=Somedata, Bucket='cloudcomputing.assignment.storage', Key=upload_path)

"""

import boto3
running_instance = []
ec2 = boto3.resource('ec2')

for instance in ec2.instances.all():
    if instance.state['Name'] == 'running':         # Choose running instance and save their instance_id
        running_instance.append(instance.id)
        print instance.id, instance.state
print running_instance

我可以获取运行实例的详细信息,有人能告诉我是否有类似于boto3中的run_instances函数,我可以使用它在我的一个正在运行的EC2实例中运行脚本SCRIPT_TORUN

4个回答

3
请参考:Boto3 run_instances 你需要的参数是:UserData='string' UserData (string) --
用户数据可用于实例。有关更多信息,请参见在启动时运行Linux实例上的命令和添加用户数据(Windows)。如果您使用命令行工具,则会为您执行base64编码,并且可以从文件中加载文本。否则,必须提供base64编码的文本。 此值将自动进行base64编码。不要在执行操作之前对此值进行base64编码。

这是否意味着我可以在获取运行实例后不使用 SSH 运行脚本?我能否指定一个实例来运行脚本,因为在 run_instances 函数中我没有找到像 'instance_id' 这样的参数。 - Coding_Rabbit

1
这是使用另一个名为paramiko的Python库完成的方法。
import paramiko

user_name='ubuntu'
instance_id='i-08h873123123' #just an example
pem_addr='/Users/folder1/.ssh/jack-aws.pem' # folder path to aws instance key
aws_region='us-east-1' 


instances = ec2.instances.filter(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])


for instance in instances:
    if (instance.id==instance_id):
        p2_instance=instance
        break;



ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
privkey = paramiko.RSAKey.from_private_key_file(pem_addr)
ssh.connect(p2_instance.public_dns_name,username=user_name,pkey=privkey)


cmd_to_run='dropbox start && source /home/ubuntu/anaconda3/bin/activate py36 && cd /home/ubuntu/xx/yy/ && python3 func1.py' #you can seperate two shell commands by && or ;
stdin4, stdout4, stderr4 = ssh.exec_command(cmd_to_run,timeout=None, get_pty=False)
ssh.close()

0
如果您想仅在EC2启动时运行一次脚本,则可以在调用run_instances时在用户数据中提供脚本。
然而,如果您想在一个或多个EC2实例上基于特定情况运行脚本,则应查看EC2系统管理器(Run Command)或类似Fabric示例)。

我能指定一个实例来运行脚本吗?因为在run_instances函数中我没有找到像“instance_id”这样的参数。 - Coding_Rabbit
run_instances函数不接受实例ID作为输入。该函数启动新的EC2实例。它返回实例ID。 - jarmod
如果我想使用现有的实例来运行脚本,而不是创建一个新的实例,该怎么办? - Coding_Rabbit
如前所述,请使用EC2 SSM或类似的工具,例如Fabric。 - jarmod
将多行脚本通过 scp 或其他方式推送到 EC2 实例上,或者从 S3 拉取脚本到 EC2 实例中,然后使用 SSM 调用该脚本。您还可以使用简单的 SSM 一行命令从 S3 检索脚本,chmod +x 脚本,然后将其作为执行 任何 脚本的通用方法执行。 - jarmod
显示剩余3条评论

0

这是我的做法

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

对于凭证,我已经添加了AWSCLI包,打开终端并运行命令

aws configure

输入细节,这些细节将被保存并自动从.aws文件夹中被boto3读取。


尝试导入任何模块时都无法正常工作。例如:import numpy。会出现错误,说numpy不存在,但如果我从ec2终端运行相同的代码,则可以正常工作。 - Aseem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接