Tous les produits
Search
Centre de documentation

Elastic Compute Service:Exécuter des commandes avec un SDK

Dernière mise à jour :Aug 18, 2026

Utilisez le SDK ECS pour exécuter des commandes Cloud Assistant sur plusieurs instances ECS et récupérer les résultats d'exécution sans vous connecter.

Scénario d'exemple

Un système d'exploitation et de maintenance (O&M) est essentiel à la stabilité de votre activité. Pour garantir la bonne santé de vos instances ECS, vérifiez régulièrement l'utilisation des ressources, telles que l'utilisation du processeur, la consommation de mémoire et l'utilisation du disque.

Cloud Assistant permet d'exécuter des commandes sur des instances ECS sans connexion, ce qui facilite l'automatisation des tâches O&M, comme la surveillance des ressources, la collecte des journaux et le dépannage.

Prérequis

Assurez-vous que les conditions suivantes sont remplies :

Opérations API utilisées

Les opérations API ECS suivantes sont utilisées :

Opération

Description

RunCommand

Exécute une commande sur une ou plusieurs instances ECS et renvoie un InvokeId pour la tâche de commande.

DescribeInvocations

Interroge les résultats d'exécution d'une commande à l'aide de l'InvokeId.

Types de commande

Cloud Assistant prend en charge trois types de commande, définis par le paramètre Type dans RunCommand :

Valeur Type

Description

RunShellScript

Commande Shell pour les instances Linux

RunBatScript

Commande Batch pour les instances Windows

RunPowerShellScript

Commande PowerShell pour les instances Windows

Valeurs d'état d'invocation

Lors de l'interrogation des résultats, le champ InvocationStatus indique l'état de la commande :

État

Description

Pending

La commande est en cours de vérification ou d'envoi.

Running

La commande est en cours d'exécution.

Stopping

L'arrêt de la commande est en cours.

Success

La commande s'est terminée avec succès.

Failed

La commande a échoué.

Stopped

La commande a été arrêtée.

Remarque

Le champ InvocationStatus est renvoyé au niveau de l'invocation par DescribeInvocations. Il utilise la valeur Success pour indiquer une fin réussie. La valeur Finished appartient au champ InstanceInvokeStatus au niveau inférieur par instance InvokeInstance, qui constitue un champ distinct avec un ensemble différent de valeurs d'énumération.

Exemple de code

Les exemples Java et Python suivants montrent comment exécuter une commande sur des instances ECS et interroger les résultats d'exécution à l'aide du SDK ECS.

Java

Cet exemple crée une classe CloudAssistantService qui initialise un client ECS, exécute une commande et interroge les résultats jusqu'à ce que la commande se termine ou expire.

Comportements clés :

  • Crée un client ECS singleton thread-safe avec verrouillage à double contrôle.

  • Exécute cat /proc/meminfo sur les instances spécifiées.

  • Effectue une interrogation toutes les 2 secondes, jusqu'à commandTimeOut / delay tentatives.

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

Cet exemple utilise des fonctions distinctes pour l'initialisation du client, l'exécution de la commande, l'interrogation des invocations et l'attente de la fin de l'exécution.

Comportements clés :

  • Valide le type de commande par rapport à RunShellScript, RunBatScript et RunPowerShellScript avant l'exécution.

  • Vérifie que la liste des ID d'instance n'est pas vide.

  • Utilise un backoff exponentiel lors de l'interrogation : le temps d'attente double à chaque tentative (2 ^ retry_count secondes).

  • Par défaut, le nombre de tentatives est défini sur max(command_timeout // 2, 1) (30 pour un délai d'expiration de 60 secondes).

  • Gère les états terminaux : Success (succès), Failed et 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()