如果您在执行云助手命令后需要重启实例,建议避免直接在云助手命令中添加reboot、shutdown等操作,否则云助手服务不能上报命令执行结果,会导致命令状态异常。本文介绍如何使用OpenAPI和运维编排服务OOS批量执行命令并重启实例,您可以根据需要选择合适的方式。
使用OpenAPI批量执行命令并重启实例
阿里云提供了丰富的OpenAPI供您管理云上资源,本步骤以在本地Linux环境中运行Python代码调用OpenAPI为例,演示如何批量执行命令并重启实例。
- 准备执行命令所需的信息。
- 获取AccessKey。建议您获取RAM用户的AccessKey,具体操作,请参见获取AccessKey。
- 获取地域ID。您可以调用DescribeRegions获取地域列表,详细的参数说明,请参见DescribeRegions。
- 获取待执行命令的实例ID。您可以调用DescribeInstances筛选符合指定条件的实例,例如状态为运行中的实例、绑定了指定标签的实例。详细的参数说明,请参见DescribeInstances。
- 获取AccessKey。
- 在本地配置环境并运行示例代码。
- 安装阿里云Python SDK。
sudo pip install aliyun-python-sdk-ecs
- 升级Python SDK至最新版本。
sudo pip install --upgrade aliyun-python-sdk-ecs
- 创建.py文件,并写入示例代码。请用您获取的信息替换示例代码中的以下信息:
- AccessKey ID:
access_key = '<yourAccessKey ID>'
- AccessKey Secret:
access_key_secret = '<yourAccessKey Secret>'
- Region ID:
region_id = '<yourRegionId>'
- 实例ID:
ins_ids= ["i-bp185fcs****","i-bp14wwh****","i-bp13jbr****"]
示例代码:# coding=utf-8 # If the Python sdk is not installed, run 'sudo pip install aliyun-python-sdk-ecs'. # Make sure you're using the latest sdk version. # Run 'sudo pip install --upgrade aliyun-python-sdk-ecs' to upgrade. import json import sys import base64 import time import logging from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest from aliyunsdkecs.request.v20140526.DescribeInvocationResultsRequest import DescribeInvocationResultsRequest from aliyunsdkecs.request.v20140526.RebootInstancesRequest import RebootInstancesRequest from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest # Configure the log output formatter logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s [%(levelname)s]: %(message)s", datefmt='%m-%d %H:%M') logger = logging.getLogger() access_key = '<yourAccessKey ID>' # 请填入您获取的AccessKey ID access_key_secret = '<yourAccessKey Secret>' # 请填入您获取的AccessKey Secret region_id = '<yourRegionId>' # 请填入您获取的Region ID client = AcsClient(access_key, access_key_secret, region_id) def base64_decode(content, code='utf-8'): if sys.version_info.major == 2: return base64.b64decode(content) else: return base64.b64decode(content).decode(code) def get_invoke_result(invoke_id): request = DescribeInvocationResultsRequest() request.set_accept_format('json') request.set_InvokeId(invoke_id) response = client.do_action_with_exception(request) response_details = json.loads(response)["Invocation"]["InvocationResults"]["InvocationResult"] dict_res = { detail.get("InstanceId",""):{"status": detail.get("InvocationStatus",""),"output":base64_decode(detail.get("Output",""))} for detail in response_details } return dict_res def get_instances_status(instance_ids): request = DescribeInstancesRequest() request.set_accept_format('json') request.set_InstanceIds(instance_ids) response = client.do_action_with_exception(request) response_details = json.loads(response)["Instances"]["Instance"] dict_res = { detail.get("InstanceId",""):{"status":detail.get("Status","")} for detail in response_details } return dict_res def run_command(cmdtype,cmdcontent,instance_ids,timeout=60): """ cmdtype: 命令类型: RunBatScript;RunPowerShellScript;RunShellScript cmdcontent: 命令内容 instance_ids 实例ID列表 """ try: request = RunCommandRequest() request.set_accept_format('json') request.set_Type(cmdtype) request.set_CommandContent(cmdcontent) request.set_InstanceIds(instance_ids) # 执行命令的超时时间,单位s,默认是60s,请根据执行的实际命令来设置合适的超时时间 request.set_Timeout(timeout) response = client.do_action_with_exception(request) invoke_id = json.loads(response).get("InvokeId") return invoke_id except Exception as e: logger.error("run command failed") def reboot_instances(instance_ids,Force=False): """ instance_ids: 需要重启的实例列表 Force: 是否强制重启,默认否 """ request = RebootInstancesRequest() request.set_accept_format('json') request.set_InstanceIds(instance_ids) request.set_ForceReboot(Force) response = client.do_action_with_exception(request) def wait_invoke_finished_get_out(invoke_id,wait_count,wait_interval): for i in range(wait_count): result = get_invoke_result(invoke_id) if set([res["status"] for _,res in result.items()]) & set(["Running","Pending","Stopping"]): time.sleep(wait_interval) else: return result return result def wait_instance_reboot_ready(ins_ids,wait_count,wait_interval): for i in range(wait_count): result = get_instances_status(ins_ids) if set([res["status"] for _,res in result.items()]) != set(["Running"]): time.sleep(wait_interval) else: return result return result def run_task(): # 设置云助手命令的命令类型 cmdtype = "RunShellScript" # 设置云助手命令的命令内容 cmdcontent = """ #!/bin/bash echo helloworld """ # 设置超时时间 timeout = 60 # 请填入需要执行命令并重启的实例的ID ins_ids= ["i-bp185fcs****","i-bp14wwh****","i-bp13jbr****"] # 执行命令 invoke_id = run_command(cmdtype,cmdcontent,ins_ids,timeout) logger.info("run command,invoke-id:%s" % invoke_id) # 等待命令执行完成,循环查询10次,每次间隔5秒,查询次数和间隔请根据实际情况配置 invoke_result = wait_invoke_finished_get_out(invoke_id,10,5) for ins_id,res in invoke_result.items(): logger.info("instance %s command execute finished,status: %s,output:%s" %(ins_id,res["status"],res["output"])) # 重启实例 logger.warn("reboot instance Now") reboot_instances(ins_ids) time.sleep(5) # 等待实例重启至Running状态,循环查询30次,每次间隔10秒 reboot_result = wait_instance_reboot_ready(ins_ids,30,10) logger.warn("reboot instance Finished") for ins_id,res in reboot_result.items(): logger.info("instance %s status: %s" %(ins_id,res["status"])) if __name__ == '__main__': run_task()
- AccessKey ID:
- 运行.py文件。运行效果如下图所示,为3台实例执行命令输出
helloworld
,然后自动重启实例。
- 安装阿里云Python SDK。
使用OOS批量执行命令并重启实例
运维编排服务OOS是阿里云提供的云上自动化运维服务,您可以通过模板定义运维动作,然后执行模板自动化运行运维任务。
- 进入模板配置页面。
- 登录OOS控制台。
- 在左侧导航栏,单击我的模板。
- 单击创建模板。
- 完成模板配置。
- 输入模板名称
runcommand_reboot_instances
。 - 单击YAML页签,并输入以下代码。
FormatVersion: OOS-2019-06-01 Description: en: Bulky run command on ECS instances and reboot instance. zh-cn: 批量在多台ECS实例上运行云助手命令并重启实例。 name-en: ACS-ECS-BulkyRunCommandRboot name-zh-cn: 批量在ECS实例上运行命令并重启实例 categories: - run_command Parameters: regionId: Type: String Description: en: The id of region zh-cn: 地域ID Label: en: Region zh-cn: 地域 AssociationProperty: RegionId Default: '{{ ACS::RegionId }}' targets: Type: Json Label: en: TargetInstance zh-cn: 目标实例 AssociationProperty: Targets AssociationPropertyMetadata: ResourceType: ALIYUN::ECS::Instance RegionId: regionId commandType: Description: en: The type of command zh-cn: 云助手命令类型 Label: en: CommandType zh-cn: 云助手命令类型 Type: String AllowedValues: - RunBatScript - RunPowerShellScript - RunShellScript Default: RunShellScript commandContent: Description: en: Command content to run in ECS instance zh-cn: 在ECS实例中执行的云助手命令 Label: en: CommandContent zh-cn: 云助手命令 Type: String MaxLength: 16384 AssociationProperty: Code Default: echo hello workingDir: Description: en: 'The directory where the created command runs on the ECS instances.Linux instances: under the home directory of the administrator (root user): /root.Windows instances: under the directory where the process of the Cloud Assistant client is located, such asC:\Windows\System32.' zh-cn: 脚本在ECS实例中的运行目录。Linux系统实例默认在管理员(root用户)的home目录下,即/root。Windows系统实例默认在云助手客户端进程所在目录,例如C:\Windows\System32。 Label: en: WorkingDir zh-cn: 运行目录 Type: String Default: '' timeout: Description: en: The value of the invocation timeout period of a command on ECS instances zh-cn: ECS实例中执行命令的超时时间 Label: en: Timeout zh-cn: 超时时间 Type: Number Default: 600 enableParameter: Description: en: Whether to include secret parameters or custom parameters in the command zh-cn: 命令中是否包含加密参数或自定义参数 Label: en: EnableParameter zh-cn: 命令中是否包含加密参数或自定义参数 Type: Boolean Default: false username: Description: en: The username that is used to run the command on the ECS instance zh-cn: 在ECS实例中执行命令的用户名称 Label: en: Username zh-cn: 执行命令的用户名称 Type: String Default: '' windowsPasswordName: Description: en: The name of the password used to run the command on a Windows instance zh-cn: 在Windows实例中执行命令的用户的密码名称 Label: en: WindowsPasswordName zh-cn: 在Windows实例中执行命令的用户的密码名称 Type: String Default: '' AssociationProperty: SecretParameterName rateControl: Description: en: Concurrency ratio of task execution zh-cn: 任务执行的并发比率 Label: en: RateControl zh-cn: 任务执行的并发比率 Type: Json AssociationProperty: RateControl Default: Mode: Concurrency MaxErrors: 0 Concurrency: 10 OOSAssumeRole: Description: en: The RAM role to be assumed by OOS zh-cn: OOS扮演的RAM角色 Label: en: OOSAssumeRole zh-cn: OOS扮演的RAM角色 Type: String Default: OOSServiceRole RamRole: '{{ OOSAssumeRole }}' Tasks: - Name: getInstance Description: en: Views the ECS instances. zh-cn: 获取ECS实例。 Action: ACS::SelectTargets Properties: ResourceType: ALIYUN::ECS::Instance RegionId: '{{ regionId }}' Filters: - '{{ targets }}' Outputs: instanceIds: Type: List ValueSelector: Instances.Instance[].InstanceId - Name: runCommand Action: ACS::ECS::RunCommand Description: en: Execute cloud assistant command. zh-cn: 执行云助手命令。 Properties: regionId: '{{ regionId }}' commandContent: '{{ commandContent }}' instanceId: '{{ ACS::TaskLoopItem }}' commandType: '{{ commandType }}' workingDir: '{{ workingDir }}' timeout: '{{ timeout }}' enableParameter: '{{ enableParameter }}' username: '{{ username }}' windowsPasswordName: '{{ windowsPasswordName }}' Loop: RateControl: '{{ rateControl }}' Items: '{{ getInstance.instanceIds }}' Outputs: commandOutputs: AggregateType: Fn::ListJoin AggregateField: commandOutput Outputs: commandOutput: Type: String ValueSelector: invocationOutput - Name: rebootInstance Action: ACS::ECS::RebootInstance Description: en: Restarts the ECS instances. zh-cn: 重启实例。 Properties: regionId: '{{ regionId }}' instanceId: '{{ ACS::TaskLoopItem }}' Loop: RateControl: '{{ rateControl }}' Items: '{{ getInstance.instanceIds }}' Outputs: instanceIds: Type: List Value: '{{ getInstance.instanceIds }}'
- 单击创建模板。
- 输入模板名称
- 执行模板。
- 找到刚创建的模板,在操作列单击创建执行。
- 完成执行配置。按提示逐步完成配置,在设置参数页面选择多台实例,其他设置保持默认即可。
- 在确定页面,单击创建。创建执行后自动开始执行模板,并跳转至执行的基本详情页面,等待执行状态变为成功后即执行完成。
- 查看执行结果。您可以在高级视图页签查看执行过程和输出,如下图所示,可以看出预定动作均已成功完成。