すべてのプロダクト
Search
ドキュメントセンター

Elastic Compute Service:SDK によるコマンドの実行

最終更新日:Apr 28, 2026

ECS SDK を使用して、複数の ECS インスタンスでクラウドアシスタントコマンドを実行し、ログインせずに実行結果を取得できます。

利用シーン

ビジネスの安定性を確保するには、O&M(運用・保守)システムが不可欠です。ECS インスタンスの健全性を維持するために、CPU 使用率、メモリ消費量、ディスク使用率などのリソース使用量を定期的に確認してください。

クラウドアシスタントは、ログインせずに ECS インスタンス上でコマンドを実行できるため、リソースモニタリング、ログ収集、トラブルシューティングなどの自動化された O&M タスクを実現します。

前提条件

以下の要件を満たしていることを確認してください。

  • 対象の ECS インスタンスが Running 状態であり、クラウドアシスタントエージェントがインストール済みである必要があります。詳細については、「クラウドアシスタントエージェントのインストール」をご参照ください。

  • ALIBABA_CLOUD_ACCESS_KEY_ID および ALIBABA_CLOUD_ACCESS_KEY_SECRET の環境変数が設定されている必要があります。詳細については、「Linux、macOS、および Windows での環境変数の設定」をご参照ください。

    説明

    Alibaba Cloud アカウントを保護するには、RAM ユーザーを作成し、そのユーザーに ECS 権限を付与して、その AccessKey ペアを使用して ECS SDK の操作を呼び出します。「RAM ユーザー」をご参照ください。

  • RAM ユーザーにクラウドアシスタントの権限が付与されている必要があります。詳細については、「RAM ユーザーによるクラウドアシスタントへのアクセス」をご参照ください。

  • クラウドアシスタントコマンド(シェル、バッチ、または PowerShell)が準備されている必要があります。

  • ECS SDK の依存関係がインストールされている必要があります。SDK Center の Elastic Compute Service ページをご確認ください。

使用する API オペレーション

以下の ECS API オペレーションを使用します。

オペレーション

説明

RunCommand

1 つまたは複数の ECS インスタンスでコマンドを実行し、コマンドタスクの InvokeId を返します。

DescribeInvocations

InvokeId を使用してコマンドの実行結果をクエリします。

コマンドタイプ

クラウドアシスタントは、RunCommandType パラメーターで指定される 3 種類のコマンドタイプをサポートしています。

Type 値

説明

RunShellScript

Linux インスタンス用のシェルコマンド

RunBatScript

Windows インスタンス用のバッチコマンド

RunPowerShellScript

Windows インスタンス用の PowerShell コマンド

呼び出しステータス値

結果をポーリングする際、InvocationStatus フィールドでコマンドの状態を確認できます。

ステータス

説明

Pending

コマンドが検証中または送信中です。

Running

コマンドが実行中です。

Stopping

コマンドが停止処理中です。

Finished

コマンドが完了しました。

Failed

コマンドが失敗しました。

Stopped

コマンドが停止されました。

サンプルコード

以下の Java および Python の例では、ECS SDK を使用して ECS インスタンスでコマンドを実行し、実行結果をポーリングする方法を示します。

Java

この例では、ECS クライアントを初期化し、コマンドを実行して、コマンドが完了またはタイムアウトするまで結果をポーリングする CloudAssistantService クラスを作成します。

主な動作:

  • ダブルチェックロックを使用して、スレッドセーフなシングルトン ECS クライアントを作成します。

  • 指定されたインスタンスで cat /proc/meminfo を実行します。

  • 2 秒間隔でポーリングを行い、最大 commandTimeOut / delay 回リトライします。

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

この例では、クライアントの初期化、コマンドの実行、呼び出しのクエリ、完了のポーリングをそれぞれ別の関数で実装しています。

主な動作:

  • 実行前にコマンドタイプを RunShellScriptRunBatScript、および RunPowerShellScript に対して検証します。

  • インスタンス ID のリストが空でないことを確認します。

  • ポーリング時にエクスポネンシャルバックオフを使用します。待ち時間はリトライごとに倍増します(2 ^ retry_count 秒)。

  • リトライ回数のデフォルト値は max(command_timeout // 2, 1) です(タイムアウトが 60 秒の場合、30 回)。

  • 終了ステータス(Finished(成功)、Failed、および 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_ids = 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_ids = [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 == "Finished":
            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()