Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2020-02-18T18:02:35.420Z
Answers: Actually best example here. More upvotes, please.
Answers: Sanctus
Answers: CC BY-SA 4.0
Answers: 2023-03-05T14:08:53.523Z
Answers: Great example: one thing worth mentioning is that the list-commands-invocations does truncate the output, if it is too long
Answers: Vorsprung
Answers: CC BY-SA 3.0
Answers: 2018-02-21T13:53:58.407Z
Answers: 2018-02-21T13:53:58.407Z
Answers: kenorb
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2018-09-28T08:28:26.247Z
Answers: 2018-09-28T17:03:47.560Z
Answers: 2018-09-28T17:03:47.560Z
Answers: ExploringApple
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2018-11-14T02:13:11.023Z
Answers: 2018-11-14T19:01:25.560Z
Answers: 2018-11-14T19:01:25.560Z
Answers: Kyle Bridenstine
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2020-09-11T09:52:09.933Z
Answers: 2020-09-11T09:52:09.933Z
Answers: Kyr
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2023-10-07T13:30:59.877Z
Answers: 2023-10-07T14:20:47.133Z
Answers: 2023-10-07T14:20:47.133Z
Answers: JonathanReez
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2020-06-20T22:10:28.170Z
Answers: Can you copy files to an instance too at the same time?
Answers: red888
Answers: CC BY-SA 3.0
Answers: 2018-02-06T13:40:27.197Z
Answers: 2018-02-06T15:47:59.173Z
Answers: 2018-02-06T15:47:59.173Z
Answers: swysocki
Body: <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>
  
Comments: CC BY-SA 3.0
Comments: 2018-02-05T16:02:27.163Z
Comments: 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.
Comments: Preston Martin
Tags: <amazon-ec2><aws-cli>
Title: How to run a script or a command on EC2 instance via AWS CLI?
UserDisplayName: kenorb
ThreadText: # 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](https://aws.amazon.com/blogs/aws/new-ec2-run-command-remote-instance-management-at-scale/) 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 "<your instance id>" --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](https://docs.aws.amazon.com/systems-manager/latest/userguide/walkthrough-cli.html) 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`](https://docs.aws.amazon.com/cli/latest/reference/ssm/send-command.html) 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?](https://devops.stackexchange.com/q/3372/3)
  
  > **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](https://www.justdocloud.com/2018/04/01/run-commands-remotely-ec2-instances/)
  
  
  ---
  
  ### 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](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html) 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}\'"
  
  ```
  
  
  ---
  
  