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-concurrencyand--max-errors 1for the fleet.
- Prefer idempotent scripts that can run twice safely.
- Use
--commentso CloudTrail and the console show why the command ran. - Restrict who can run
AWS-RunShellScriptagainst production with IAM conditions onssm: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