Home / AWS

AWSCheat sheetBeginner

SSM Run Command cheat sheet - running scripts across EC2 fleets safely with rate control and output to S3

Run shell or PowerShell commands on many instances at once with SSM Run Command. Target by tag, limit concurrency and errors, send output to S3, and check results per instance, with no SSH or RDP needed.

Deepak Bhardwaj4 min read

Applies toAWS Systems Manager Run Command; Linux and Windows EC2 instances and hybrid nodes with SSM Agent; AWS CLI v2

Before you start

  • Instances must be managed nodes: SSM Agent running, an instance profile with AmazonSSMManagedInstanceCore, and a network path to the SSM endpoints (internet, NAT or VPC endpoints).
  • Check what SSM can see:
aws ssm describe-instance-information \
  --query "InstanceInformationList[].{id:InstanceId,ping:PingStatus,os:PlatformName,agent:AgentVersion}" --output table

PingStatus must be Online.

Run a command

One instance, Linux:

aws ssm send-command --instance-ids i-0abc123 \
  --document-name AWS-RunShellScript \
  --parameters 'commands=["uptime","df -h /"]' \
  --comment "disk check" --query "Command.CommandId" --output text

By tag, Windows, with rate control:

aws ssm send-command \
  --targets Key=tag:Env,Values=prod Key=tag:Role,Values=web \
  --document-name AWS-RunPowerShellScript \
  --parameters 'commands=["Get-Service W3SVC | Select Status","(Get-PSDrive C).Free/1GB"]' \
  --max-concurrency 10% --max-errors 2 \
  --timeout-seconds 600 \
  --output-s3-bucket-name my-ssm-output --output-s3-key-prefix runcommand/ \
  --cloud-watch-output-config CloudWatchOutputEnabled=true,CloudWatchLogGroupName=/ssm/runcommand
Option What it does
--targets Key=tag:<k>,Values=<v> Select instances by tag (multiple keys = AND)
--targets Key=resource-groups:Name,Values=<group> Select by resource group
--max-concurrency 10% or 5 How many run at once
--max-errors 2 or 5% Stop sending to new instances after this many failures
--timeout-seconds How long to wait for delivery before giving up
executionTimeout parameter How long the script itself may run (default 3600 s)

Set the script runtime limit like this:

--parameters '{"commands":["/opt/app/rotate-logs.sh"],"executionTimeout":["1800"]}'

Check results

CMD=<command-id>

# overall status per instance
aws ssm list-command-invocations --command-id $CMD \
  --query "CommandInvocations[].{id:InstanceId,status:Status}" --output table

# output for one instance (stdout truncated to 24,000 chars; full output goes to S3)
aws ssm get-command-invocation --command-id $CMD --instance-id i-0abc123 \
  --query "{status:Status,rc:ResponseCode,out:StandardOutputContent,err:StandardErrorContent}"

# only failures
aws ssm list-command-invocations --command-id $CMD --details \
  --query "CommandInvocations[?Status!='Success'].{id:InstanceId,status:Status,detail:StatusDetails}" --output table
Status Meaning
Success Script exited 0
Failed Non-zero exit code; read stderr
TimedOut Script exceeded executionTimeout
Undeliverable / DeliveryTimedOut Agent offline or unreachable
Cancelled Stopped by you or by max-errors

Useful one-liners

Restart a service on all web servers, two at a time:

aws ssm send-command --targets Key=tag:Role,Values=web --max-concurrency 2 --max-errors 1 \
  --document-name AWS-RunShellScript --parameters 'commands=["sudo systemctl restart nginx","systemctl is-active nginx"]'

Find which hosts have a package version:

aws ssm send-command --targets Key=tag:Env,Values=prod --document-name AWS-RunShellScript \
  --parameters 'commands=["rpm -q openssl || dpkg -l openssl | tail -1"]'

(SSM Inventory is better for ongoing package reporting.)

Run a script stored in S3:

aws ssm send-command --targets Key=tag:Env,Values=test --document-name AWS-RunRemoteScript \
  --parameters '{"sourceType":["S3"],"sourceInfo":["{\"path\":\"https://my-scripts.s3.amazonaws.com/fix.sh\"}"],"commandLine":["fix.sh"]}'

Cancel a running command:

aws ssm cancel-command --command-id $CMD

Safety habits

Warning

A tag-targeted command runs on every matching instance, including ones you forgot about. Run it on a single instance first, then use a low --max-concurrency and --max-errors 1 for the fleet.

  • Prefer idempotent scripts that can run twice safely.
  • Use --comment so CloudTrail and the console show why the command ran.
  • Restrict who can run AWS-RunShellScript against production with IAM conditions on ssm:resourceTag/Env.
  • For multi-step, approval-gated or scheduled work, use SSM Automation runbooks or State Manager associations instead of ad-hoc commands.

Troubleshooting

Problem Check
Instance missing from targets Agent offline, wrong tag, or no instance profile
Undeliverable No route to SSM endpoints, or the agent is stopped
Output cut off Read the S3 output, which isn't truncated
Works manually, fails via SSM Script runs as root/SYSTEM with a different PATH and environment

Agent logs are at /var/log/amazon/ssm/amazon-ssm-agent.log on Linux and C:\ProgramData\Amazon\SSM\Logs\amazon-ssm-agent.log on Windows.

Checklist

  • Targets confirmed Online
  • Tested on one instance
  • Concurrency and error limits set
  • Output to S3 or CloudWatch
  • Failures reviewed per instance