<p>Here is a helper Bash script which uses <a href="https://docs.aws.amazon.com/cli/latest/reference/ssm/send-command.html" rel="noreferrer"><code>aws ssm send-command</code></a> to run the commands:</p>

<pre><code>#/usr/bin/env bash -x
# Script to run PowerShell script on the Windows instance.
instanceId="$1"
cmdId=$(aws ssm send-command --instance-ids "$instanceId" --document-name "AWS-RunPowerShellScript" --query "Command.CommandId" --output text --parameters commands="'${@:2}'")
[ $? -ne 0 ] &amp;&amp; { echo "Usage: $0 instance_id command"; exit 1; }
while [ "$(aws ssm list-command-invocations --command-id "$cmdId" --query "CommandInvocations[].Status" --output text)" == "InProgress" ]; do sleep 1; done
aws ssm list-command-invocations --command-id "$cmdId" --details --query "CommandInvocations[*].CommandPlugins[*].Output[]" --output text
</code></pre>

<p>Usage:</p>

<pre><code> ./run_ec2_ps_cmd.sh instance-id command
</code></pre>

<p>Example:</p>

<pre><code>$ ./run_ec2_ps_cmd.sh i-xyz hostname
ip-xyz
</code></pre>

<p><sup>To execute larger outputs, see: <a href="https://devops.stackexchange.com/q/3372/3">How to avoid output being truncated when running AWS SSM command?</a></sup></p>

CC BY-SA 4.0
2020-02-18T18:02:35.420Z
Actually best example here. More upvotes, please.
Sanctus
CC BY-SA 4.0
2023-03-05T14:08:53.523Z
Great example: one thing worth mentioning is that the list-commands-invocations does truncate the output, if it is too long
Vorsprung
CC BY-SA 3.0
2018-02-21T13:53:58.407Z
2018-02-21T13:53:58.407Z
kenorb
<p>Yes, you can do this with AWS Systems manager. AWS Systems Manager Run Command allows you to remotely and securely run set of commands on EC2 as well on-premise server. Below are high-level steps to achieve this.</p>

<p>Attach Instance IAM role:
The ec2 instance must have IAM role with policy AmazonSSMFullAccess. This role enables the instance to communicate with the Systems Manager API.</p>

<p>Install SSM Agent:
The EC2 instance must have SSM agent installed on it. The SSM Agent process the run command requests &amp; configure the instance as per command.</p>

<p>Execute command :
Example usage via AWS CLI:</p>

<p>Execute the following command to retrieve the services running on the instance. Replace Instance-ID with ec2 instance id.</p>

<pre><code>aws ssm send-command --document-name "AWS-RunShellScript" --comment "listing services" --instance-ids "Instance-ID" --parameters commands="service --status-all" --region us-west-2 --output text
</code></pre>

<p>More detailed information: <a href="https://www.justdocloud.com/2018/04/01/run-commands-remotely-ec2-instances/" rel="nofollow noreferrer">here</a></p>

CC BY-SA 4.0
2018-09-28T08:28:26.247Z
2018-09-28T17:03:47.560Z
2018-09-28T17:03:47.560Z
ExploringApple
<p>Here is something super cool I do with AWS SSM Send-Command!</p>

<p>Using Apache Airflow I create a brand new EC2-Instance using a Cloud Formation Template (or CFT for short) that's just a JSON file with all the configuration values for my EC2-Instance that I want; also note that in this CFT I also have a bootstrap command that copies a Python script from an S3 location to the new EC2-Instance so that I can execute it later on using an SSM Send-Command! I do this using Python3 and the AWS SDK for Python3 called the Boto3 library. Here's part of the command for creating the new CFT Stack that in turn creates my new EC2-Instance:</p>

<pre><code>import boto3

cft = boto3.client("cloudformation", "us-east-1")

response = cft.create_stack(
    StackName='foobarStackName',
    TemplateBody=json.dumps(json_data))
</code></pre>

<p>Then I can get the Instance-ID of the new EC2-Instance (required to use SSM Send-Command) using something like this:</p>

<pre><code>response = cft.describe_stacks(
    StackName='foobarStackName',
)
</code></pre>

<p>Then I can get the Instance-ID of the current Airflow Worker's server's EC2-Instance by running this command <code>wget -q -O - http://169.254.169.254/latest/meta-data/instance-id</code> through Python:</p>

<pre><code>output = subprocess.Popen(['wget', '-q', '-O', '-', 'http://169.254.169.254/latest/meta-data/instance-id'],
                          stdout=subprocess.PIPE)

# Do some weird stuff to get the value (I'm a Java developer so excuse my bad Python skilz)
instanceId = output.communicate()    
instanceId = str(instanceId).split("'")[1]
</code></pre>

<p><strong>NOW!!!! FOR THE GRAND FINALE</strong></p>

<p>I can then execute a script on the new EC2-Instance I created and send that script whatever parameters/arguments I want... including the Instance-ID of the server that sent the SSM Send-Command so that way when my script is done running on the new EC2-Instance it can send another SSM Send-Command back to my Airflow server to tell it that the script is finished. This is at a very high level without details but it's just to demonstrate an idea :)</p>

<pre><code>subprocess.run(shlex.split('sudo aws ssm send-command --document-name "AWS-RunShellScript" --parameters commands=["sudo python3 /home/ec2-user/ec2_file_sensor.py ' + filepath + ' ' + batchIdValue + ' ' + source + ' ' + fileType + ' ' + airflowWorkerInstanceId + '"] --instance-ids ' + ec2ResourceInstanceId + ' --region us-east-1'))
</code></pre>

<p><em>Not sure if this helped anyone but it's a cool and FUN example of doing something with the AWS SSM Send-Command! Albeit, probably a code smell xD</em></p>

CC BY-SA 4.0
2018-11-14T02:13:11.023Z
2018-11-14T19:01:25.560Z
2018-11-14T19:01:25.560Z
Kyle Bridenstine
<p>If you need to execute more than just one command, because let's say you are investigating an issue, you can start a session:</p>
<pre><code>aws ssm start-session --target i-0123456789abcdef0
</code></pre>
<p>You will need to <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html" rel="nofollow noreferrer">install Session Manager Plugin</a> for that.</p>

CC BY-SA 4.0
2020-09-11T09:52:09.933Z
2020-09-11T09:52:09.933Z
Kyr
<p>I've slightly improved the script by @kenorb as it wasn't working for me in 2023. It now accepts the region name as a parameter and properly extracts the CommandID:</p>
<pre><code>#!/usr/bin/env bash

# Script to run a shell script on a Linux instance

while getopts &quot;r:i:&quot; opt; do
  case $opt in
    r) regionId=&quot;$OPTARG&quot; ;;
    i) instanceId=&quot;$OPTARG&quot; ;;
    *) echo &quot;Usage: $0 -r region_id -i instance_id command&quot;
       exit 1
       ;;
  esac
done

# Remove the flags from the positional parameters
shift $((OPTIND -1))

# Check if regionId and instanceId are provided
if [[ -z &quot;$regionId&quot; || -z &quot;$instanceId&quot; ]]; then
  echo &quot;Usage: $0 -r region_id -i instance_id command&quot;
  exit 1
fi

cmdId=$(aws ssm send-command --document-name &quot;AWS-RunShellScript&quot; --targets &quot;Key=instanceids,Values=$instanceId&quot; --region &quot;$regionId&quot; --output text --parameters commands=&quot;'$*'&quot; | grep -Eo '([a-z0-9])+-([a-z0-9])+-([a-z0-9])+-([a-z0-9])+-([a-z0-9])+')
[ $? -ne 0 ] &amp;&amp; { echo &quot;Failed to send command&quot;; exit 1; }

while [ &quot;$(aws ssm list-command-invocations --region &quot;$regionId&quot; --command-id &quot;$cmdId&quot; --query &quot;CommandInvocations[].Status&quot; --output text)&quot; == &quot;InProgress&quot; ]; do
  sleep 0.5
done

aws ssm list-command-invocations --region &quot;$regionId&quot; --command-id &quot;$cmdId&quot; --details --query &quot;CommandInvocations[*].CommandPlugins[*].Output[]&quot; --output text 
</code></pre>
<p>Results in:</p>
<pre><code>./run_ec2_ps_cmd.sh -i i-INSERTINSTANCEIDHERE -r us-east-1 'echo &quot;Hello World!&quot;'
Hello World!
</code></pre>
<p>Don't forget to escape quotes and parameters (dollar signs) in the input, i.e.:</p>
<pre><code>./run_ec2_ps_cmd.sh -i i-INSERTINSTANCEIDHERE -r us-east-1 &quot;netstat -tuln | awk \'{print \$4}\'&quot;
</code></pre>

CC BY-SA 4.0
2023-10-07T13:30:59.877Z
2023-10-07T14:20:47.133Z
2023-10-07T14:20:47.133Z
JonathanReez
<p>To run ipconfig from the AWS Systems Manager Run Command:</p>

<pre><code>$ aws ssm send-command --document-name "AWS-RunPowerShellScript" --instance-ids "&lt;your instance id&gt;" --parameters commands=ipconfig
</code></pre>

<p><sup>Note: If you've got the error, consider specifying the right <code>--region</code>.</sup></p>

<p>This assumes you have your AWS credentials and CLI configured properly. See <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/walkthrough-cli.html" rel="noreferrer">Systems Manager Run Command Walkthrough Using the AWS CLI</a> for more information.</p>

<hr>

<p>Here is the practical shell command example of sending and getting the command output:</p>

<pre><code>cmdid=$(aws ssm send-command --instance-ids "i-ch3ng3th1s" --document-name "AWS-RunPowerShellScript" --parameters commands=ipconfig --query "Command.CommandId" --output text)
aws ssm list-command-invocations --command-id "$cmdid" --details --query "CommandInvocations[*].CommandPlugins[*].Output[]" --output text
</code></pre>

CC BY-SA 4.0
2020-06-20T22:10:28.170Z
Can you copy files to an instance too at the same time?
red888
CC BY-SA 3.0
2018-02-06T13:40:27.197Z
2018-02-06T15:47:59.173Z
2018-02-06T15:47:59.173Z
swysocki
<p>According to <a href="https://aws.amazon.com/blogs/aws/new-ec2-run-command-remote-instance-management-at-scale/" rel="noreferrer">New EC2 Run Command</a> news article, AWS CLI should support a new sub-command to execute scripts on remote EC2 instances.</p>

<p>However I've checked in <code>aws ec2 help</code>, but I can't find the relevant command.</p>

<p>I've installed <code>aws</code> via <code>apt-get</code>:</p>

<pre><code>$ aws --version
aws-cli/1.14.32 Python/3.5.4 Linux/4.12.7-64 botocore/1.8.36
</code></pre>

<p>Which sub-command I should look for and what's the syntax to run, let say <code>ipconfig</code> in <em>PowerShell</em> on the remote EC2 instance?</p>

CC BY-SA 3.0
2018-02-05T16:02:27.163Z
FYI that article is from 2015 so I wouldn't call it a "new" sub-command. I checked out the source code repository (https://github.com/aws/aws-cli) for the aws-cli, and I couldn't find any mention of it in the docs, examples, release notes, or through briefly looking through the code. I filed an issue (https://github.com/aws/aws-cli/issues/3126) and will submit an answer when I get feedback.
Preston Martin
<amazon-ec2><aws-cli>
How to run a script or a command on EC2 instance via AWS CLI?
kenorb
# How to run a script or a command on EC2 instance via AWS CLI?

(Asked by: username_0 on 2018-02-05)

According to New EC2 Run Command news article, AWS CLI should support a new sub-command to execute scripts on remote EC2 instances.
However I've checked in aws ec2 help, but I can't find the relevant command.
I've installed aws via apt-get:
$ aws --version
aws-cli/1.14.32 Python/3.5.4 Linux/4.12.7-64 botocore/1.8.36

Which sub-command I should look for and what's the syntax to run, let say ipconfig in PowerShell on the remote EC2 instance?

**Tags:** amazon-ec2, aws-cli

> **Comments:**
> **username_1**: FYI that article is from 2015 so I wouldn't call it a "new" sub-command. I checked out the source code repository (https://github.com/aws/aws-cli) for the aws-cli, and I couldn't find any mention of it in the docs, examples, release notes, or through briefly looking through the code. I filed an issue (https://github.com/aws/aws-cli/issues/3126) and will submit an answer when I get feedback.  

---

## 6 answers

### Answer by username_8 on 2018-02-06. Score: 15 | Accepted answer

To run ipconfig from the AWS Systems Manager Run Command:
$ aws ssm send-command --document-name "AWS-RunPowerShellScript" --instance-ids "" --parameters commands=ipconfig

Note: If you've got the error, consider specifying the right --region.
This assumes you have your AWS credentials and CLI configured properly. See Systems Manager Run Command Walkthrough Using the AWS CLI for more information.

Here is the practical shell command example of sending and getting the command output:
cmdid=$(aws ssm send-command --instance-ids "i-ch3ng3th1s" --document-name "AWS-RunPowerShellScript" --parameters commands=ipconfig --query "Command.CommandId" --output text)
aws ssm list-command-invocations --command-id "$cmdid" --details --query "CommandInvocations[*].CommandPlugins[*].Output[]" --output text

> **Comments:**
> **username_9**: Can you copy files to an instance too at the same time?  

---

### Answer by username_0 on 2018-02-21. Score: 7

Here is a helper Bash script which uses aws ssm send-command to run the commands:
#/usr/bin/env bash -x
# Script to run PowerShell script on the Windows instance.
instanceId="$1"
cmdId=$(aws ssm send-command --instance-ids "$instanceId" --document-name "AWS-RunPowerShellScript" --query "Command.CommandId" --output text --parameters commands="'${@:2}'")
[ $? -ne 0 ] && { echo "Usage: $0 instance_id command"; exit 1; }
while [ "$(aws ssm list-command-invocations --command-id "$cmdId" --query "CommandInvocations[].Status" --output text)" == "InProgress" ]; do sleep 1; done
aws ssm list-command-invocations --command-id "$cmdId" --details --query "CommandInvocations[*].CommandPlugins[*].Output[]" --output text

Usage:
 ./run_ec2_ps_cmd.sh instance-id command

Example:
$ ./run_ec2_ps_cmd.sh i-xyz hostname
ip-xyz

To execute larger outputs, see: How to avoid output being truncated when running AWS SSM command?

> **Comments:**
> **username_2**: Actually best example here. More upvotes, please.  
> **username_3**: Great example: one thing worth mentioning is that the list-commands-invocations does truncate the output, if it is too long  

---

### Answer by username_4 on 2018-09-28. Score: 3

Yes, you can do this with AWS Systems manager. AWS Systems Manager Run Command allows you to remotely and securely run set of commands on EC2 as well on-premise server. Below are high-level steps to achieve this.
Attach Instance IAM role:
The ec2 instance must have IAM role with policy AmazonSSMFullAccess. This role enables the instance to communicate with the Systems Manager API.
Install SSM Agent:
The EC2 instance must have SSM agent installed on it. The SSM Agent process the run command requests & configure the instance as per command.
Execute command :
Example usage via AWS CLI:
Execute the following command to retrieve the services running on the instance. Replace Instance-ID with ec2 instance id.
aws ssm send-command --document-name "AWS-RunShellScript" --comment "listing services" --instance-ids "Instance-ID" --parameters commands="service --status-all" --region us-west-2 --output text

More detailed information: here


---

### Answer by username_5 on 2018-11-14. Score: 3

Here is something super cool I do with AWS SSM Send-Command!
Using Apache Airflow I create a brand new EC2-Instance using a Cloud Formation Template (or CFT for short) that's just a JSON file with all the configuration values for my EC2-Instance that I want; also note that in this CFT I also have a bootstrap command that copies a Python script from an S3 location to the new EC2-Instance so that I can execute it later on using an SSM Send-Command! I do this using Python3 and the AWS SDK for Python3 called the Boto3 library. Here's part of the command for creating the new CFT Stack that in turn creates my new EC2-Instance:
import boto3

cft = boto3.client("cloudformation", "us-east-1")

response = cft.create_stack(
    StackName='foobarStackName',
    TemplateBody=json.dumps(json_data))

Then I can get the Instance-ID of the new EC2-Instance (required to use SSM Send-Command) using something like this:
response = cft.describe_stacks(
    StackName='foobarStackName',
)

Then I can get the Instance-ID of the current Airflow Worker's server's EC2-Instance by running this command wget -q -O - http://169.254.169.254/latest/meta-data/instance-id through Python:
output = subprocess.Popen(['wget', '-q', '-O', '-', 'http://169.254.169.254/latest/meta-data/instance-id'],
                          stdout=subprocess.PIPE)

# Do some weird stuff to get the value (I'm a Java developer so excuse my bad Python skilz)
instanceId = output.communicate()    
instanceId = str(instanceId).split("'")[1]

NOW!!!! FOR THE GRAND FINALE
I can then execute a script on the new EC2-Instance I created and send that script whatever parameters/arguments I want... including the Instance-ID of the server that sent the SSM Send-Command so that way when my script is done running on the new EC2-Instance it can send another SSM Send-Command back to my Airflow server to tell it that the script is finished. This is at a very high level without details but it's just to demonstrate an idea :)
subprocess.run(shlex.split('sudo aws ssm send-command --document-name "AWS-RunShellScript" --parameters commands=["sudo python3 /home/ec2-user/ec2_file_sensor.py ' + filepath + ' ' + batchIdValue + ' ' + source + ' ' + fileType + ' ' + airflowWorkerInstanceId + '"] --instance-ids ' + ec2ResourceInstanceId + ' --region us-east-1'))

Not sure if this helped anyone but it's a cool and FUN example of doing something with the AWS SSM Send-Command! Albeit, probably a code smell xD


---

### Answer by username_6 on 2020-09-11. Score: 0

If you need to execute more than just one command, because let's say you are investigating an issue, you can start a session:
aws ssm start-session --target i-0123456789abcdef0

You will need to install Session Manager Plugin for that.


---

### Answer by username_7 on 2023-10-07. Score: 0

I've slightly improved the script by @username_0 as it wasn't working for me in 2023. It now accepts the region name as a parameter and properly extracts the CommandID:
#!/usr/bin/env bash

# Script to run a shell script on a Linux instance

while getopts "r:i:" opt; do
  case $opt in
    r) regionId="$OPTARG" ;;
    i) instanceId="$OPTARG" ;;
    *) echo "Usage: $0 -r region_id -i instance_id command"
       exit 1
       ;;
  esac
done

# Remove the flags from the positional parameters
shift $((OPTIND -1))

# Check if regionId and instanceId are provided
if [[ -z "$regionId" || -z "$instanceId" ]]; then
  echo "Usage: $0 -r region_id -i instance_id command"
  exit 1
fi

cmdId=$(aws ssm send-command --document-name "AWS-RunShellScript" --targets "Key=instanceids,Values=$instanceId" --region "$regionId" --output text --parameters commands="'$*'" | grep -Eo '([a-z0-9])+-([a-z0-9])+-([a-z0-9])+-([a-z0-9])+-([a-z0-9])+')
[ $? -ne 0 ] && { echo "Failed to send command"; exit 1; }

while [ "$(aws ssm list-command-invocations --region "$regionId" --command-id "$cmdId" --query "CommandInvocations[].Status" --output text)" == "InProgress" ]; do
  sleep 0.5
done

aws ssm list-command-invocations --region "$regionId" --command-id "$cmdId" --details --query "CommandInvocations[*].CommandPlugins[*].Output[]" --output text 

Results in:
./run_ec2_ps_cmd.sh -i i-INSERTINSTANCEIDHERE -r us-east-1 'echo "Hello World!"'
Hello World!

Don't forget to escape quotes and parameters (dollar signs) in the input, i.e.:
./run_ec2_ps_cmd.sh -i i-INSERTINSTANCEIDHERE -r us-east-1 "netstat -tuln | awk \'{print \$4}\'"


---

