本教程指引您如何通过云助手在ECS实例上批量执行一条echo 123的命令,达到自动化运维实例的目的。通过云助手,您可以配置自动化批量处理日常维护任务,降低人工维护所耗费的大量时间和精力、始终保持您的ECS实例的最佳状态、提升故障排查效率。

前提条件

无论您通过哪种方式使用云助手,目标实例必须满足以下条件:
  • 实例已安装云助手客户端。如何安装,请参见云助手客户端
  • 实例状态为运行中Running)。
  • 实例网络类型为专有网络(VPC)。详情请参见专有网络(VPC)
  • 执行PowerShell命令时,Windows实例已经配置了PowerShell模块。更多详情,请参见安装Windows PowerShell

使用方式

方法一:通过阿里云CLI调用API

通过阿里云CLI调用API之前,请确保已完成以下操作:
  • 本示例在命令行工具中完成,请确保您已经安装了阿里云命令行工具CLI。如何获取和安装阿里云CLI,请参见阿里云命令行工具CLI
  • 已获取地域ID,示例命令中需要填写。详细的地域ID,请参见地域和可用区

本示例调用API时仅传入了部分基本必需参数,执行结果均采用默认设置。您可以阅读API文档后自定义运行命令,优化运行效果。例如,在创建命令时为命令自定义设置执行目录(WorkingDir)和超时时间(TimeOut)等。完成以下操作,通过阿里云CLI调用API:

  1. 可选: 检查实例状态,若实例的状态不是运行中Running),调用StartInstance接口运行目标实例。
    aliyun ecs StartInstance --InstanceId i-bp1g6zv0ce8ogXXXXXXp
  2. 可选: 调用DescribeCloudAssistantStatus接口查询目标实例是否安装了云助手客户端。
    当返回CloudAssistantStatus=true结果时,表示您的实例已安装云助手客户端。否则请调用InstallCloudAssistant接口为实例安装客户端。
  3. 调用CreateCommand接口创建一份名为test的云助手命令,命令内容为echo 123,并使用Base64编码明文命令。
    aliyun ecs CreateCommand --RegionId TheRegionId --CommandContent ZWNobyAxMjM= --Type RunShellScript --Name test --Description test --Output cols=CommandId
    云助手支持如下三种命令类型:
    • Shell脚本(RunShellScript):支持Linux实例。
    • PowerShell脚本(RunPowerShellScript):支持Windows实例。
    • Bat脚本(RunBatScript):支持Windows实例。
    如果目标实例为Windows实例,将Type修改为RunBatScript或者RunPowershellScript
  4. 调用InvokeCommand接口为一台或多台实例执行已创建的云助手命令。
    aliyun ecs InvokeCommand --RegionId TheRegionId --InstanceId.1 i-bp1g6zv0ce8ogXXXXXXp --InstanceId.2 i-bp1g6zv0ce8ogXXXXXXp --CommandId your-command-id --Timed false --Output cols=InvokeId
    • Timed表示是否为周期性任务,True表示周期性任务,False表示不是周期性任务。
    • 当命令为周期性任务时,通过参数Frequency指定运行周期,例如0 */20 * * * *表示周期为每20分钟。

      更多关于Cron表达式详情,请参见Cron表达式取值说明

  5. 调用DescribeInvocations接口查看命令执行状态。其中,InvokeId是执行命令时返回的执行ID。
    aliyun ecs DescribeInvocations --RegionId TheRegionId --InvokeId your-invoke-id
    说明 返回参数InvokeStatusFinished时仅表示命令进程执行完成,不代表一定有预期的命令效果,您需要通过DescribeInvocationResults中的参数Output查看实际的具体执行结果。
  6. 调用DescribeInvocationResults查看指定实例的命令的实际执行结果。
    aliyun ecs DescribeInvocationResults --RegionId TheRegionId --InstanceId i-bp1g6zv0ce8ogXXXXXXp --InvokeId your-invoke-id

方法二:通过ECS Python SDK调用API

通过ECS Python SDK调用API之前,请确保已完成以下操作:
  • 您需要使用2.1.2及以上版本的Python SDK。更多详情,请前往GitHub Repo Alibaba Cloud获取最新版本ECS SDK。
  • 示例SDK中需要您自行填写AccessKey和地域ID,请确保您已经获取了AccessKeyId和AccessKeySecret。更多详情,请参见创建AccessKey地域和可用区
示例代码如下:
# 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 logging
import os
import time
import datetime
import base64
from aliyunsdkcore import client

from aliyunsdkecs.request.v20140526.CreateCommandRequest import CreateCommandRequest
from aliyunsdkecs.request.v20140526.InvokeCommandRequest import InvokeCommandRequest
from aliyunsdkecs.request.v20140526.DescribeInvocationResultsRequest import DescribeInvocationResultsRequest

# configuration the log output formatter, if you want to save the output to file,
# append ",filename='ecs_invoke.log'" after datefmt.
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',filename='aliyun_assist_openapi_test.log', filemode='w')
#access_key = 'Your Access Key Id'
#acess_key_secrect = 'Your Access Key Secrect'
#region_name = 'cn-shanghai'
#zone_id = 'cn-shanghai-b'

access_key = 'LTAIXXXXXXXXXXXX'  # 请根据实际情况填写
acess_key_secrect = '4dZXXXXXXXXXXXXXXXXXXXXXXXX'  # 请根据实际情况填写
region_name = 'cn-hangzhou'  # 请根据实际情况填写
zone_id = 'cn-hangzhou-f'  # 请根据实际情况填写

clt = client.AcsClient(access_key, acess_key_secrect, region_name)

def create_command(command_content, type, name, description):
    request = CreateCommandRequest()
    request.set_CommandContent(command_content)
    request.set_Type(type)
    request.set_Name(name)
    request.set_Description(description)
    response = _send_request(request)
    if response is None:
        return None
    command_id = response.get('CommandId')
    return command_id;

def invoke_command(instance_id, command_id, timed, cronat):
    request = InvokeCommandRequest()
    request.set_Timed(timed)
    InstanceIds = [instance_id]
    request.set_InstanceIds(InstanceIds)
    request.set_CommandId(command_id)
    request.set_Frequency(cronat)
    response = _send_request(request)
    invoke_id = response.get('InvokeId')
    return invoke_id;

def get_task_output_by_id(instance_id, invoke_id):
    logging.info("Check instance %s invoke_id is %s", instance_id, invoke_id)
    request = DescribeInvocationResultsRequest()
    request.set_InstanceId(instance_id)
    request.set_InvokeId(invoke_id)
    response = _send_request(request)
    invoke_detail = None
    output = None
    if response is not None:
        result_list = response.get('Invocation').get('InvocationResults').get('InvocationResult')
        for item in result_list:
            invoke_detail = item
            output = base64.b64decode(item.get('Output'))
            break;
        return output;

def execute_command(instance_id):
    command_str = 'yum check-update'
    command_id = create_command(base64.b64encode(command_str), 'RunShellScript', 'test', 'test')
    if(command_id is None):
        logging.info('create command failed')
        return

    invoke_id = invoke_command(instance_id, command_id, 'false', '')
    if(invoke_id is None):
        logging.info('invoke command failed')
        return

    time.sleep(15)

    output = get_task_output_by_id(instance_id, invoke_id)
    if(output is None):
        logging.info('get result failed')
        return

    logging.info("output: %s is \n", output)

# send open api request
def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action(request)
        logging.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        logging.error(e)

if __name__ == '__main__':
    execute_command('i-bp17zhpbXXXXXXXXXXXXX')
				

方法三:通过控制台使用云助手

通过控制台使用云助手的步骤,请参见新建命令