aws ssm send-command: Run Commands on Instances
aws ssm send-command executes commands on SSM-managed EC2 instances over the Systems Manager channel, no SSH keys or open ports required.
For deploy hooks on EC2 (pull image, restart service) without exposing SSH, send-command runs a Run Command document against tagged instances and returns a command ID to poll.
What it does
aws ssm send-command runs the SSM document --document-name (commonly AWS-RunShellScript) on the instances chosen by --targets or --instance-ids, passing inputs via --parameters. It returns a CommandId you poll with get-command-invocation. Instances must run the SSM agent and have an instance profile granting SSM.
Common usage
CMD=$(aws ssm send-command \
--document-name AWS-RunShellScript \
--targets 'Key=tag:role,Values=web' \
--parameters 'commands=["systemctl restart app"]' \
--query 'Command.CommandId' --output text)
aws ssm wait command-executed \
--command-id "$CMD" --instance-id i-0123456789abcdef0Options
| Flag | What it does |
|---|---|
| --document-name <doc> | SSM document, e.g. AWS-RunShellScript |
| --instance-ids <id...> | Target by explicit instance ID |
| --targets Key=tag:..,Values=.. | Target by tag (preferred for fleets) |
| --parameters commands=[..] | Document inputs (commands for shell script) |
| --comment <text> | Label shown in command history |
| --query Command.CommandId | Capture the ID to poll |
In CI
Target by tag (Key=tag:role,Values=web) so the command applies to the whole fleet without hardcoding IDs. send-command returns immediately; poll with aws ssm wait command-executed or get-command-invocation to get exit status and output, because the initial call does not wait for the script to finish.
Common errors in CI
"An error occurred (InvalidInstanceId) when calling the SendCommand operation" usually means the target is not SSM-managed: the agent is down, the instance lacks an SSM instance profile, or no instance matched the tag filter. "AccessDeniedException" means missing ssm:SendCommand. A command that "succeeds" to send but reports Failed in get-command-invocation means the script itself exited non-zero; read StandardErrorContent.