Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
计划启动EC2实例并在其中运行python脚本_Python_Amazon Web Services_Amazon Ec2 - Fatal编程技术网

计划启动EC2实例并在其中运行python脚本

计划启动EC2实例并在其中运行python脚本,python,amazon-web-services,amazon-ec2,Python,Amazon Web Services,Amazon Ec2,我试图在AWS中安排python脚本,但是我不希望实例一直运行。因此,尝试将以下过程自动化: 在特定时间启动EC2实例 在其中运行python脚本 作业完成后停止EC2实例 我无法将此脚本直接作为Lambda函数运行,因为该脚本执行一些需要更多RAM的并行处理,因此选择更大的AWS实例,而不是将其作为Lambda函数编写。另外,我不希望这个实例一直运行,因为它很昂贵 到目前为止,我遵循并创建了一个Lambda函数来在特定时间启动和停止实例,但是在实例启动后,我找不到运行python脚本的方法 有

我试图在AWS中安排python脚本,但是我不希望实例一直运行。因此,尝试将以下过程自动化:

  • 在特定时间启动EC2实例
  • 在其中运行python脚本
  • 作业完成后停止EC2实例
  • 我无法将此脚本直接作为Lambda函数运行,因为该脚本执行一些需要更多RAM的并行处理,因此选择更大的AWS实例,而不是将其作为Lambda函数编写。另外,我不希望这个实例一直运行,因为它很昂贵

    到目前为止,我遵循并创建了一个Lambda函数来在特定时间启动和停止实例,但是在实例启动后,我找不到运行python脚本的方法


    有人能给我指出正确的方向吗?

    我的应用程序每天运行一个实例@13:39 UST,处理完成后自动关闭。它在下面使用

  • 使用云监视事件规则的计划lambda函数
  • lambda触发器将启动一个实例(使用硬编码id)
  • 导入boto3
    def lambda_处理程序(事件、上下文):
    ec2=boto3.客户('ec2',地区名称='ap-south-1')
    ec2.start_实例(instanceId=['i-xxxxxxx'])
    print('startedyour instances:'+str('i-xxxxxx'))
    
    return
    对于解决此问题的未来开发人员,一种更新的方法是:

  • 使用包含
    amazonec2roleforsm
    策略的角色创建EC2
  • 创建lambda来执行唤醒、运行命令和关机
  • 使用Cloudwatch事件触发lambda
  • 因此:

  • 按照以下步骤操作:

  • 使用以下lambda骨架:

  • 导入时间
    进口boto3
    地区名称='us-east-1'
    工作目录=“”
    COMMAND=”“”
    回声:“你好,世界!"
    """
    实例_ID=“”
    def start_ec2():
    ec2=boto3.client('ec2',region\u name=region\u name)
    ec2.start\u实例(instanceId=[INSTANCE\u ID])
    尽管如此:
    response=ec2.描述实例状态(instanceId=[instance\u ID],includealInstances=True)
    状态=响应['InstanceStatus'][0]['InstanceState']
    打印(f“状态:{state['Code']}-{state['Name']}”)
    #如果状态为16(“正在运行”),则继续,否则,等待5秒钟,然后重试
    如果状态['Code']==16:
    打破
    其他:
    时间。睡眠(5)
    打印('EC2已启动')
    def stop_ec2():
    ec2=boto3.client('ec2',region\u name=region\u name)
    ec2.stop_实例(instanceId=[INSTANCE_ID])
    尽管如此:
    response=ec2.描述实例状态(instanceId=[instance\u ID],includealInstances=True)
    状态=响应['InstanceStatus'][0]['InstanceState']
    打印(f“状态:{state['Code']}-{state['Name']}”)
    #如果状态为80(“已停止”),则继续,否则等待5秒钟,然后重试
    如果状态['Code']==80:
    打破
    其他:
    时间。睡眠(5)
    打印('实例已停止')
    def run_命令():
    client=bot3.client('ssm',region\u name=region\u name)
    时间。睡眠(10)#我必须等待10秒才能“发送_命令”找到我的实例
    cmd\u response=client.send\u命令(
    InstanceId=[INSTANCE_ID],
    DocumentName='AWS-RunShellScript',
    DocumentVersion=“1”,
    TimeoutSeconds=300,
    MaxConcurrency=“1”,
    CloudWatchOutputConfig={'CloudWatchOutputEnabled':True},
    参数={
    “命令”:[命令],
    “executionTimeout”:[“300”],
    “工作目录”:[工作目录],
    },
    )
    command_id=cmd_response['command']['CommandId']
    时间。睡眠(1)#再次,我必须等待1s才能获取_命令#调用识别我的命令#id
    retcode=-1
    尽管如此:
    输出=client.get_命令_调用(
    CommandId=命令\u id,
    InstanceId=实例ID,
    )
    #如果ResponseCode为-1,则该命令仍在运行,因此请等待5秒钟,然后重试
    retcode=output['ResponseCode']
    如果重新编码!=-1:
    打印('状态:',输出['Status'])
    打印('StdOut:',输出['StandardOutputContent'])
    打印('StdErr:',输出['StandardErrorContent'])
    打破
    打印('状态:',重新编码)
    时间。睡眠(5)
    打印(“命令成功完成”)#实际上,0表示成功,其他任何东西都表示失败,但这对我来说并不重要
    返回代码
    def lambda_处理程序(事件、上下文):
    retcode=-1
    尝试:
    启动_ec2()
    retcode=run_命令()
    最后:#与发生的情况无关,尝试关闭EC2
    停止_ec2()
    返回代码
    
  • 按照以下步骤操作:

  • 我在使用本文中的解决方案启动和停止实例时遇到问题。然后我按照上面的说明去做,真的很简单。基本上:

  • 转到左侧的,单击策略,然后单击创建策略。然后单击JSON选项卡。然后复制粘贴此项以创建新策略:
  • 转到并在左侧选择角色。确保选择Lambda作为AWS服务,并附加在步骤1中创建的策略

  • 然后转到Lambda控制台,单击创建函数。选择Python3.7,然后单击权限旁边的下拉列表,使用现有角色并附加在步骤2中创建的IAM角色

  • 使用以下代码:

  • 启动EC2实例,键入
    whichpython
    ,找到python的路径并将其写下来。然后,键入
    crontab-e
    编辑您的CRON作业。不要使用
    sudo
    …因为当您没有使用它来运行Python文件时,有时
    sudo
    会把事情搞砸。在我的例子中,我有一个
    pgpass
    文件存储我的密码,而
    sudo
    看不到,但是删除sudo有效
  • W
    import time
    import boto3
    
    REGION_NAME = 'us-east-1'
    
    WORKING_DIRECTORY = '<YOUR WORKING DIRECTORY, IF ANY>'
    
    COMMAND = """
        echo "Hello, world!"
        """
    
    INSTANCE_ID = '<YOUR INSTANCE ID>'
    
    
    def start_ec2():
        ec2 = boto3.client('ec2', region_name=REGION_NAME)
        ec2.start_instances(InstanceIds=[INSTANCE_ID])
    
        while True:
            response = ec2.describe_instance_status(InstanceIds=[INSTANCE_ID], IncludeAllInstances=True)
            state = response['InstanceStatuses'][0]['InstanceState']
    
            print(f"Status: {state['Code']} - {state['Name']}")
    
            # If status is 16 ('running'), then proceed, else, wait 5 seconds and try again
            if state['Code'] == 16:
                break
            else:
                time.sleep(5)
    
        print('EC2 started')
    
    
    def stop_ec2():
        ec2 = boto3.client('ec2', region_name=REGION_NAME)
        ec2.stop_instances(InstanceIds=[INSTANCE_ID])
    
        while True:
            response = ec2.describe_instance_status(InstanceIds=[INSTANCE_ID], IncludeAllInstances=True)
            state = response['InstanceStatuses'][0]['InstanceState']
    
            print(f"Status: {state['Code']} - {state['Name']}")
    
            # If status is 80 ('stopped'), then proceed, else wait 5 seconds and try again
            if state['Code'] == 80:
                break
            else:
                time.sleep(5)
    
        print('Instance stopped')
    
    
    def run_command():
        client = boto3.client('ssm', region_name=REGION_NAME)
    
        time.sleep(10)  # I had to wait 10 seconds to "send_command" find my instance 
    
        cmd_response = client.send_command(
            InstanceIds=[INSTANCE_ID],
            DocumentName='AWS-RunShellScript',
            DocumentVersion="1",
            TimeoutSeconds=300,
            MaxConcurrency="1",
            CloudWatchOutputConfig={'CloudWatchOutputEnabled': True},
            Parameters={
                'commands': [COMMAND],
                'executionTimeout': ["300"],
                'workingDirectory': [WORKING_DIRECTORY],
            },
        )
    
        command_id = cmd_response['Command']['CommandId']
        time.sleep(1)  # Again, I had to wait 1s to get_command_invocation recognises my command_id
    
        retcode = -1
        while True:
            output = client.get_command_invocation(
                CommandId=command_id,
                InstanceId=INSTANCE_ID,
            )
    
            # If the ResponseCode is -1, the command is still running, so wait 5 seconds and try again
            retcode = output['ResponseCode']
            if retcode != -1:
                print('Status: ', output['Status'])
                print('StdOut: ', output['StandardOutputContent'])
                print('StdErr: ', output['StandardErrorContent'])
                break
    
            print('Status: ', retcode)
            time.sleep(5)
    
        print('Command finished successfully') # Actually, 0 means success, anything else means a fail, but it didn't matter to me
        return retcode
    
    
    def lambda_handler(event, context):
        retcode = -1
        try:
            start_ec2()
            retcode = run_command()
        finally:  # Independently of what happens, try to shutdown the EC2
            stop_ec2()
    
        return retcode
    
    
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
          ],
          "Resource": "arn:aws:logs:*:*:*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "ec2:Start*",
            "ec2:Stop*"
          ],
          "Resource": "*"
        }
      ]
    }
    
    import boto3
    region = 'us-west-1' # Dont use the specific, like instead of us-east-1d just write us-east-1
    instances = ['i-xxxxxxxxxxxx']
    ec2 = boto3.client('ec2', region_name=region)
    
    def lambda_handler(event, context):
        ec2.start_instances(InstanceIds=instances)
        print('started your instances: ' + str(instances))
    
    import boto3
    region = 'us-west-1' # Dont use the specific, like instead of us-east-1d just write us-east-1
    instances = ['i-xxxxxxxxxxxx']
    ec2 = boto3.client('ec2', region_name=region)
    
    ec2.stop_instances(InstanceIds=instances)