AWS Systems Manager(SSM)のaws ssm send-commandを使えば、SSH接続・踏み台サーバー不要で複数のEC2インスタンスに対して一括でシェルスクリプトを実行できます。タグフィルターと組み合わせると、マルチAZ構成の全インスタンスを一度に対象にできるため、定期メンテナンスや設定変更の自動化に最適です。
この記事では、aws ssm send-commandの設計前提から基本構文、マルチAZ環境での実践的な活用パターンまでを、実際のCLI出力例を交えて解説します。
この記事のポイント
・aws ssm send-command でタグ指定した複数EC2に同時実行できる
・IAMロールとSSM Agentで踏み台不要・SSH不要のセキュア実行が可能
・MaxConcurrency/MaxErrorsでリスクをコントロールできる
・get-command-invocationでインスタンス単位に結果確認できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜaws ssm send-commandを使うのか|SSH一斉接続との根本的な違い
マルチAZ構成のEC2インスタンスに同じ作業を行う場合、従来のSSHベースの手順はいくつかの問題を抱えています。・プライベートサブネットのインスタンスには踏み台サーバーが別途必要になる
・インスタンスごとにSSHの接続設定(鍵・ポート・セキュリティグループの22番許可)が必要
・並列実行のためのツール(Ansible・SSH並列ループ)を別途用意しなければならない
AWS SSM Run Command(aws ssm send-command)は、SSM AgentがインストールされたEC2インスタンスに対して、AWSのコントロールプレーン経由でコマンドを配信する仕組みです。SSH接続を使わないため、パブリックIPが不要で22番ポートも開ける必要がありません。
| 比較軸 | SSH一斉実行 | aws ssm send-command |
|---|---|---|
| 踏み台サーバー | 必要(プライベートサブネット) | 不要 |
| 22番ポート開放 | 必要 | 不要 |
| 認証方式 | SSH鍵 | IAMロール |
| マルチAZ対象指定 | 手動でIPリスト | タグフィルター |
| 実行結果の一元管理 | なし(各ターミナル) | CloudWatch Logs / S3 |
前提設計|SSM Agentの確認とIAMロール最小権限の設定
1. SSM Agentの動作確認とインスタンスのオンライン確認
Amazon Linux 2・Amazon Linux 2023ではSSM Agentがデフォルトでインストールされています。まずEC2インスタンス上でAgentが動いているか確認しましょう。# SSM Agentのステータス確認 $ sudo systemctl status amazon-ssm-agent * amazon-ssm-agent.service - amazon-ssm-agent Loaded: loaded (/usr/lib/systemd/system/amazon-ssm-agent.service; enabled) Active: active (running) since Wed 2026-09-10 09:14:23 UTC; 3 weeks 4 days ago Main PID: 812 (amazon-ssm-agen)
# SSMに登録されているインスタンス一覧(オンライン状態のみ表示) $ aws ssm describe-instance-information \ --filters "Key=PingStatus,Values=Online" \ --query "InstanceInformationList[*].{ID:InstanceId,IP:IPAddress,Status:PingStatus}" \ --output table \ --region ap-northeast-1 ------------------------------------------------------------------- | DescribeInstanceInformation | +------------------------+---------------+---------+ | ID | IP | Status | +------------------------+---------------+---------+ | i-0a1b2c3d4e5f6789 | 10.0.1.45 | Online | | i-0f9e8d7c6b5a4321 | 10.0.2.67 | Online | | i-0c1d2e3f4a5b6c7d | 10.0.3.89 | Online | | i-0d4e5f6a7b8c9012 | 10.0.1.102 | Online | | i-0e5f6a7b8c9d0ef3 | 10.0.2.114 | Online | | i-0f6a7b8c9d0e1f24 | 10.0.3.128 | Online | +------------------------+---------------+---------+
2. IAMロールの最小権限設計(AmazonSSMManagedInstanceCore)
EC2インスタンスにIAMインスタンスプロファイルを付与します。AWS管理ポリシーAmazonSSMManagedInstanceCoreを使うのが最小権限の基本設計です。・AmazonSSMManagedInstanceCore:Run Command・Session Manager・Patch Manager・State Managerの実行に必要な最小ポリシー
・S3バケットへの実行ログ保存が必要な場合は、対象バケットへの
s3:PutObject権限を追加する・CloudWatch Logsへの転送が必要な場合は、
logs:CreateLogGroupとlogs:PutLogEventsを追加するTerraformでロールを定義する場合は以下のようになります。
# Terraform: SSM実行用IAMロール定義(最小権限) resource "aws_iam_role" "ssm_ec2" { name = "ssm-ec2-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } }] }) } resource "aws_iam_role_policy_attachment" "ssm_core" { role = aws_iam_role.ssm_ec2.name policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } resource "aws_iam_instance_profile" "ssm_ec2" { name = "ssm-ec2-instance-profile" role = aws_iam_role.ssm_ec2.name }
3. VPCエンドポイント設計(インターネット非公開環境)
プライベートサブネット内のEC2インスタンスからSSMを使う場合、インターネット経由を避けるためにVPCエンドポイントを設定します。以下の3つのエンドポイントが必要です。・com.amazonaws.ap-northeast-1.ssm:Run Command・SSM管理トラフィック
・com.amazonaws.ap-northeast-1.ssmmessages:Session Manager用
・com.amazonaws.ap-northeast-1.ec2messages:EC2との通信
S3ログ保存を使う場合はGateway型のS3エンドポイントも追加します。各エンドポイントのセキュリティグループはEC2のセキュリティグループからのインバウンド443番(HTTPS)を許可する設定にします。VPCエンドポイントとSSM Agentの構成設計を含むAWS環境全般の基礎については、AWSをLinuxエンジニアが学ぶための基礎講座も参考にしてください。
aws ssm send-commandの基本構文と一括実行手順
1. ターゲット指定|インスタンスIDとタグフィルター
aws ssm send-commandのターゲット指定は2通りあります。方法1:インスタンスIDを直接指定
# 2台のインスタンスを直接指定してdf -hを実行 $ aws ssm send-command \ --instance-ids "i-0a1b2c3d4e5f6789" "i-0f9e8d7c6b5a4321" \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["df -h"]' \ --region ap-northeast-1
# Env=prod タグのついた全インスタンスを対象に一括実行 $ aws ssm send-command \ --targets "Key=tag:Env,Values=prod" \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["df -h","free -m"]' \ --region ap-northeast-1
2. コマンドの送信とパラメータ設計
実際にディスク使用率の確認スクリプトをマルチAZ全台に送信する例を見てみましょう。$ aws ssm send-command \ --targets "Key=tag:Env,Values=prod" \ "Key=tag:Role,Values=web" \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["echo "=== $(hostname) ==="","df -h /","free -m"]' \ --timeout-seconds 60 \ --max-concurrency "50%" \ --max-errors "1" \ --output-s3-bucket-name "my-ssm-logs-bucket" \ --output-s3-key-prefix "run-command/prod-web/2026-10-08" \ --region ap-northeast-1 { "Command": { "CommandId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "DocumentName": "AWS-RunShellScript", "ExpiresAfter": "2026-10-08T16:14:23.000000+00:00", "Status": "Pending", "TargetCount": 6, "CompletedCount": 0, "ErrorCount": 0 } }
・--document-name AWS-RunShellScript:任意のシェルスクリプトを実行するAWS提供ドキュメント
・--parameters commands=[...]:実行コマンドをJSON配列で指定(複数行スクリプトも可能)
・--timeout-seconds:コマンドの最大実行時間(秒)。長時間処理は適切に延ばす
・--max-concurrency:同時実行数。50%と指定するとターゲット数の半分ずつ順番に実行
・--max-errors:エラーが許容できる上限数。この数を超えると残りの実行を中断する
3. 実行結果の確認(get-command-invocation)
CommandIdを使ってインスタンス単位の実行結果を確認します。# 特定インスタンスの実行結果(標準出力・標準エラー)を確認 $ aws ssm get-command-invocation \ --command-id "a1b2c3d4-e5f6-7890-abcd-ef1234567890" \ --instance-id "i-0a1b2c3d4e5f6789" \ --region ap-northeast-1 { "CommandId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "InstanceId": "i-0a1b2c3d4e5f6789", "Status": "Success", "StatusDetails": "Success", "StandardOutputContent": "=== ip-10-0-1-45.ap-northeast-1.compute.internal ===\nFilesystem Size Used Avail Use% Mounted on\n/dev/xvda1 30G 8.2G 22G 28% /\n total used free\nMem: 7786 4123 2108\n", "StandardErrorContent": "" }
list-command-invocationsを使います。# 全インスタンスの実行ステータスを一覧表示 $ aws ssm list-command-invocations \ --command-id "a1b2c3d4-e5f6-7890-abcd-ef1234567890" \ --query "CommandInvocations[*].{Instance:InstanceId,Status:Status}" \ --output table \ --region ap-northeast-1 -------------------------------------------- | ListCommandInvocations | +------------------------+------------------+ | Instance | Status | +------------------------+------------------+ | i-0a1b2c3d4e5f6789 | Success | | i-0f9e8d7c6b5a4321 | Success | | i-0c1d2e3f4a5b6c7d | Success | | i-0d4e5f6a7b8c9012 | Success | | i-0e5f6a7b8c9d0ef3 | Success | | i-0f6a7b8c9d0e1f24 | Success | +------------------------+------------------+
マルチAZ冗長設計での活用パターン
1. 複数AZにまたがるタグベースの一括実行設計
マルチAZ構成では、各インスタンスにEnv・Role・AZなどのタグを統一して付与しておくと、send-commandのターゲット設計が柔軟になります。・全AZの全台に一括適用する場合:
--targets "Key=tag:Env,Values=prod"・特定AZだけ先行実行して様子見する場合:
--targets "Key=tag:Env,Values=prod" "Key=tag:AZ,Values=ap-northeast-1a"・特定ロールだけ対象にする場合:
--targets "Key=tag:Role,Values=web"タグを2つ指定するとAND条件になるため、「prod環境のwebサーバーだけ」という絞り込みが1コマンドで実現できます。インスタンスの増減があっても、タグが正しく付いていれば対象リストは自動で変わります。
2. MaxConcurrencyとMaxErrorsでリスクをコントロールする
本番のマルチAZ構成に対して一括でスクリプトを実行するときは、想定外の失敗が全台に波及しないよう、--max-concurrencyと--max-errorsを必ず設定してください。・--max-concurrency:同時に実行するインスタンス数。
1(1台ずつ順次)から100%(全台同時)まで指定可能。本番は25%~50%が目安・--max-errors:許容できるエラー数の上限。
0にすると1台でも失敗した時点で残りの実行をキャンセル。1~2が実務上の標準冗長設計を崩さないために、
--max-concurrency "25%"を指定してAZ間でローリング的に展開するのがおすすめです。AZをまたいだ冗長構成の設計パターン全般はAWSマルチAZ冗長設計の実践ガイドも参照してください。3. 実行ログのS3保存とCloudWatch Logsへの転送設計
マルチAZの全インスタンスに一括実行した場合、標準出力・標準エラーをS3またはCloudWatch Logsに保存しておくと、事後のトラブルシュートが楽になります。# S3とCloudWatch Logs両方に出力を保存するセキュリティパッチ適用例 $ aws ssm send-command \ --targets "Key=tag:Env,Values=prod" \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["yum update -y --security 2>&1"]' \ --timeout-seconds 600 \ --max-concurrency "25%" \ --max-errors "1" \ --output-s3-bucket-name "my-ssm-logs-bucket" \ --output-s3-key-prefix "security-patch/2026-10-08" \ --cloud-watch-output-config \ 'CloudWatchOutputEnabled=true,CloudWatchLogGroupName=/ssm/run-command/prod' \ --region ap-northeast-1
トラブルシュート|よくあるエラーと対処法
「An error occurred (InvalidInstanceId) when calling the SendCommand operation」原因:対象インスタンスがSSMに登録されていない(SSM AgentがOfflineかIAMロール未設定)
対処:
aws ssm describe-instance-informationでPingStatus=Onlineを確認。IAMインスタンスプロファイルにAmazonSSMManagedInstanceCoreが付与されているか確認するStatus: Failed / StatusDetails: executionTimedOut
原因:スクリプトが
--timeout-secondsの設定時間内に終了しなかった対処:
--timeout-secondsを増やすか、スクリプトをより短い単位に分割する。yum updateなど長時間処理は600秒以上に設定するタグフィルターで対象が0件になる
原因:タグキー/バリューの大文字小文字が一致していない、またはタグが付与されていない
対処:
aws ec2 describe-instances --filters "Name=tag:Env,Values=prod" --query "Reservations[*].Instances[*].InstanceId"でタグが付いているインスタンスを事前確認するプライベートサブネットのインスタンスがOnlineにならない
原因:VPCエンドポイントが未設定か、エンドポイントのセキュリティグループが443番ポートを許可していない
対処:VPCエンドポイント(ssm・ssmmessages・ec2messages)の作成とセキュリティグループのインバウンド443番許可を確認する。エンドポイントは各サブネットに1つずつ配置する必要がある
本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| SSM Agentの状態確認 | sudo systemctl status amazon-ssm-agent |
| SSMオンライン状態のインスタンス一覧 | aws ssm describe-instance-information --filters "Key=PingStatus,Values=Online" |
| タグ指定で一括スクリプト実行 | aws ssm send-command --targets "Key=tag:Env,Values=prod" --document-name "AWS-RunShellScript" --parameters 'commands=["cmd"]' |
| インスタンス単位の実行結果確認 | aws ssm get-command-invocation --command-id "..." --instance-id "i-xxx" |
| 全インスタンスのステータス一覧 | aws ssm list-command-invocations --command-id "..." |
| コマンド実行のキャンセル | aws ssm cancel-command --command-id "a1b2c3d4-e5f6-7890-abcd-ef1234567890" |
| 実行ログのS3保存付き一括実行 | aws ssm send-command --targets "Key=tag:Env,Values=prod" --document-name "AWS-RunShellScript" --parameters 'commands=["cmd"]' --output-s3-bucket-name "bucket" |
AWSをゼロから体系的に学べる入門講座を用意しています。
>> AWS Amazon Linux サーバー構築入門はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AWS SSM Get Parameterを活用したマルチ環境VPC秘密設定管理設計|dev/stg/prod分離
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます