Todos os produtos
Search
Central de documentação

Elastic Compute Service:Run commands with an SDK

Última atualização: Jul 03, 2026

Use o SDK do ECS para executar comandos do Cloud Assistant em várias instâncias ECS e obter os resultados da execução sem fazer login.

Cenário de exemplo

Um sistema de O&M é fundamental para a estabilidade dos negócios. Para manter a integridade das instâncias ECS, verifique regularmente o uso de recursos, como utilização de CPU, consumo de memória e uso de disco.

O Cloud Assistant executa comandos nas instâncias ECS sem necessidade de login, o que permite automatizar tarefas de O&M, incluindo monitoramento de recursos, coleta de logs e solução de problemas.

Pré-requisitos

Verifique se os seguintes requisitos foram atendidos:

Operações de API usadas

Este tópico usa as seguintes operações da API do ECS:

Operação

Descrição

RunCommand

Executa um comando em uma ou mais instâncias ECS e retorna um InvokeId para a tarefa de comando.

DescribeInvocations

Consulta os resultados da execução de um comando por InvokeId.

Tipos de comando

O Cloud Assistant oferece suporte a três tipos de comando, definidos pelo parâmetro Type em RunCommand:

Valor de Type

Descrição

RunShellScript

Comando Shell para instâncias Linux

RunBatScript

Comando Batch para instâncias Windows

RunPowerShellScript

Comando PowerShell para instâncias Windows

Valores de status de invocação

Durante a consulta periódica de resultados, o campo InvocationStatus indica o estado do comando:

Status

Descrição

Pending

O comando está sendo verificado ou enviado.

Running

O comando está em execução.

Stopping

O comando está sendo interrompido.

Success

O comando foi concluído com êxito.

Failed

O comando falhou.

Stopped

O comando foi interrompido.

Nota

InvocationStatus é o campo no nível de invocação retornado por DescribeInvocations. Ele usa Success para indicar conclusão bem-sucedida. O valor Finished pertence a InstanceInvokeStatus no subnível por instância InvokeInstance, um campo separado com um conjunto diferente de valores de enumeração.

Código de exemplo

Os exemplos a seguir em Java e Python demonstram como executar um comando em instâncias ECS e consultar periodicamente os resultados da execução com o SDK do ECS.

Java

Este exemplo cria uma classe CloudAssistantService que inicializa um cliente ECS, executa um comando e consulta os resultados periodicamente até que o comando seja concluído ou atinja o tempo limite.

Comportamentos principais:

  • Cria um cliente ECS singleton thread-safe com bloqueio de verificação dupla.

  • Executa cat /proc/meminfo nas instâncias especificadas.

  • Consulta a intervalos de 2 segundos, até commandTimeOut / delay tentativas.

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.google.gson.Gson;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class CloudAssistantService {

    /**
     * Read the AccessKey ID and AccessKey secret from environment variables.
     */
    private static final String ACCESS_KEY_ID = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    private static final String ACCESS_KEY_SECRET = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    private static final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
    private static volatile Client ecsClient;

    private CloudAssistantService() {
    }

    /**
     * Initialize the ECS client.
     *
     * @param regionId The region ID that specifies where the ECS client connects.
     * @return The initialized ECS client.
     * <p>
     * This method uses the double-checked locking pattern to ensure thread-safe
     * singleton creation of the ECS client. It first checks whether a client
     * already exists, then re-checks within a synchronized block before creating one.
     */
    public static Client getEcsClient(String regionId) throws Exception {
        if (ecsClient == null) {
            synchronized (CloudAssistantService.class) {
                if (ecsClient == null) {
                    Config config = new Config().setAccessKeyId(ACCESS_KEY_ID).setAccessKeySecret(ACCESS_KEY_SECRET).setRegionId(regionId);
                    ecsClient = new Client(config);
                }
            }
        }
        return ecsClient;
    }

    public static void main(String[] args_) {
        try {
            // The region ID.
            String regionId = "cn-chengdu";
            getEcsClient(regionId);
            // The IDs of the ECS instances on which to run the command.
            List<String> instanceIds = Arrays.asList("i-2vcXXXXXXXXXXXXXXXb8", "i-2vcXXXXXXXXXXXXXXXot");
            // The command to run.
            String commandContent = "#!/bin/bash\n cat /proc/meminfo";
            // The command execution timeout, in seconds.
            long commandTimeOut = 60;

            // Run the command.
            String invokeId = runCommand(commandContent, regionId, instanceIds, commandTimeOut);
            // Query the command execution results.
            DescribeInvocationsResponse invocationResult = describeInvocations(regionId, invokeId, commandTimeOut);
            System.out.println("The command execution result:" + new Gson().toJson(invocationResult));
            // Note: This sample does not include logging configuration.

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            SCHEDULER.shutdown();
        }
    }

    /**
     * Run a command on the specified ECS instances.
     *
     * @param commandContent The command to run.
     * @param regionId       The region ID of the target ECS instances.
     * @param instanceIds    The IDs of the target ECS instances.
     * @param commandTimeOut The command execution timeout, in seconds.
     * @return The invocation ID (InvokeId) of the command task.
     */
    public static String runCommand(String commandContent, String regionId, List<String> instanceIds, long commandTimeOut) {
        try {
            System.out.println("runCommand start...");
            RunCommandRequest request = new RunCommandRequest();
            request.setRegionId(regionId);
            request.setType(Constants.COMMAND_TYPE.RUN_SHELL_SCRIPT);
            request.setCommandContent(commandContent);
            request.setInstanceId(instanceIds);
            request.setTimeout(commandTimeOut);
            RunCommandResponse runCommandResponse = ecsClient.runCommand(request);
            return runCommandResponse.body.invokeId;
        } catch (Exception e) {
            throw new RuntimeException("runCommand failed", e);
        }
    }

    /**
     * Query the execution results of a Cloud Assistant command.
     *
     * @param regionId       The region ID of the target instances.
     * @param invokeId       The invocation ID that uniquely identifies the command task.
     * @param commandTimeOut The command execution timeout, in seconds.
     */
    public static DescribeInvocationsResponse describeInvocations(String regionId, String invokeId, long commandTimeOut) {
        DescribeInvocationsRequest describeInvocationsRequest = new DescribeInvocationsRequest()
                .setRegionId(regionId)
                .setInvokeId(invokeId);

        long delay = 2;
        // Maximum number of polling retries.
        int maxRetries = (int) (commandTimeOut / delay);
        int retryCount = 0;

        try {
            while (retryCount < maxRetries) {
                ScheduledFuture<DescribeInvocationsResponse> future = SCHEDULER.schedule(() ->
                        ecsClient.describeInvocations(describeInvocationsRequest), delay, TimeUnit.SECONDS);
                DescribeInvocationsResponse results = future.get();
                List<DescribeInvocationsResponseBody.DescribeInvocationsResponseBodyInvocationsInvocation> invocationList = results.body.invocations.invocation;
                if (invocationList.isEmpty()) {
                    throw new RuntimeException("The command execution result was not found.");
                }
                DescribeInvocationsResponseBody.DescribeInvocationsResponseBodyInvocationsInvocation invocationResult = results.body.invocations.invocation.get(0);
                String invocationStatus = invocationResult.invocationStatus;
                switch (invocationStatus) {
                    case Constants.INVOCATION_STATUS.PENDING:
                    case Constants.INVOCATION_STATUS.RUNNING:
                    case Constants.INVOCATION_STATUS.STOPPING:
                        retryCount++;
                        continue;
                    default:
                        return results;
                }
            }
            throw new RuntimeException("Max retries exceeded for command execution result.");
        } catch (Exception e) {
            throw new RuntimeException("describeInvocationResults failed", e);
        }
    }

    public static class Constants {
        // Command types.
        public static final class COMMAND_TYPE {
            // Shell command, applicable to Linux instances.
            public static final String RUN_SHELL_SCRIPT = "RunShellScript";
            // Batch command, applicable to Windows instances.
            public static final String RUN_BAT_SCRIPT = "RunBatScript";
            // PowerShell command, applicable to Windows instances.
            public static final String RUN_POWERSHELL_SCRIPT = "RunPowerShellScript";
        }

        // Invocation status values for Cloud Assistant commands.
        public static final class INVOCATION_STATUS {
            // The system is verifying or sending the command.
            public static final String PENDING = "Pending";
            // The command is being run on the ECS instances.
            public static final String RUNNING = "Running";
            // The command is being stopped.
            public static final String STOPPING = "Stopping";
        }
    }
}

Python

Este exemplo usa funções separadas para inicialização do cliente, execução de comandos, consulta de invocações e verificação periódica de conclusão.

Comportamentos principais:

  • Valida o tipo de comando comparando com RunShellScript, RunBatScript e RunPowerShellScript antes da execução.

  • Verifica se a lista de IDs de instância não está vazia.

  • Aplica backoff exponencial durante as consultas: o tempo de espera dobra a cada tentativa (2 ^ retry_count segundos).

  • Define como padrão max(command_timeout // 2, 1) tentativas (30 para um tempo limite de 60 segundos).

  • Trata estados terminais: Success (êxito), Failed e Stopped.

import os
import time
import logging
from alibabacloud_ecs20140526 import models as ecs_20140526_models
from alibabacloud_ecs20140526.client import Client as Ecs20140526Client
from alibabacloud_tea_openapi import models as open_api_models

# Configure logging.
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

ACCESS_KEY_ID = os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
ACCESS_KEY_SECRET = os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")

if not ACCESS_KEY_ID or not ACCESS_KEY_SECRET:
    raise EnvironmentError(
        "Missing required environment variables: ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET")

def get_ecs_client(region_id):
    config = open_api_models.Config(
        access_key_id=ACCESS_KEY_ID,
        access_key_secret=ACCESS_KEY_SECRET,
        region_id=region_id
    )
    return Ecs20140526Client(config)

def execute_command(client, command_content, region_id, instance_ids, command_timeout, command_type):
    if not instance_ids:
        raise ValueError("Instance IDs list cannot be empty.")

    valid_command_types = ["RunShellScript", "RunBatScript", "RunPowerShellScript"]
    if command_type not in valid_command_types:
        raise ValueError(f"Invalid command type: {command_type}. Valid types are {valid_command_types}.")

    request = ecs_20140526_models.RunCommandRequest()
    request.region_id = region_id
    request.type = command_type
    request.command_content = command_content
    request.instance_id = instance_ids
    request.timeout = command_timeout

    try:
        run_command_response = client.run_command(request)
        return run_command_response.to_map()['body']['InvokeId']
    except Exception as e:
        logging.error(f"Failed to execute command: {e}")
        raise

def query_invocations(client, region_id, invoke_id):
    request = ecs_20140526_models.DescribeInvocationsRequest()
    request.region_id = region_id
    request.invoke_id = invoke_id

    try:
        describe_invocations_response = client.describe_invocations(request)
        return describe_invocations_response.to_map()['body']
    except Exception as e:
        logging.error(f"Failed to query invocations: {e}")
        raise

def wait_for_command_completion(client, region_id, invoke_id, max_retries, backoff_factor=2):
    retry_count = 0
    while retry_count < max_retries:
        time.sleep(backoff_factor ** retry_count)
        results = query_invocations(client, region_id, invoke_id)
        invocation_list = results.get('Invocations', {}).get('Invocation', [])
        if not invocation_list:
            raise RuntimeError("The command execution result was not found.")

        invocation_result = invocation_list[0]
        invocation_status = invocation_result.get('InvocationStatus')
        logging.info(f"Current invocation status: {invocation_status}")

        if invocation_status == "Success":
            print("query_invocations result:", results)
            break
        elif invocation_status in ["Failed", "Stopped"]:
            raise RuntimeError(f"Command execution failed with status: {invocation_status}")
        else:
            retry_count += 1
    else:
        raise TimeoutError("Command execution timed out.")

def main():
    # The region ID.
    region_id = "cn-chengdu"
    # The IDs of the ECS instances on which to run the command.
    instance_ids = ["i-2vcXXXXXXXXXXXXXXXb8", "i-2vcXXXXXXXXXXXXXXXot"]
    # The command to run.
    command_content = "#!/bin/bash\n cat /proc/meminfo"
    # The command execution timeout, in seconds.
    command_timeout = 60
    # The command type. Valid values: RunShellScript, RunBatScript, and RunPowerShellScript.
    command_type = "RunShellScript"

    client = get_ecs_client(region_id)
    invoke_id = execute_command(client, command_content, region_id, instance_ids, command_timeout, command_type)

    max_retries = max(int(command_timeout // 2), 1)
    wait_for_command_completion(client, region_id, invoke_id, max_retries)

if __name__ == "__main__":
    main()