2

I'm trying to do a simple AWS CLI command that can run a shell command to multiple instances.

I know first I need to get the list of instances ids:

aws ec2 describe-instances --filter "Name=tag:Group,Values=Development" --query 'Reservations[].Instances[].[InstanceId]' --output text

I then will have to assign them to an array. Then loop through each instance id and send the command.

Do we have an option for aws to send a shell command to an instance with a specific id?

Something like this:

aws ssm send-command --instance-ids "i-xxxxxxxxxxxxxxxx" --document-name "shellscript"

I keep getting this error:

An error occurred (InvalidInstanceId) when calling the SendCommand operation:

I've made sure that the SSM agent is running on that specific instance and made sure everything is correct according to these docs pages.

kenorb
  • 155,785
  • 88
  • 678
  • 743
  • Possible duplicate of [InvalidInstanceId: An error occurred (InvalidInstanceId) when calling the SendCommand operation](https://stackoverflow.com/questions/47034797/invalidinstanceid-an-error-occurred-invalidinstanceid-when-calling-the-sendco) – kenorb Feb 07 '18 at 16:47

2 Answers2

6

You can use ssm send-command.

A sample command to see ip address of instance:

aws ssm send-command --instance-ids "your id's" --document-name "AWS-RunShellScript" --comment "IP config" --parameters "commands=ifconfig" --output text

Modify command as per your needs.


In case you've got the error, this can happen when you don't have SSM setup on the instance you're trying to access. For a list of instances where you can run SSM commands, run:

aws ssm describe-instance-information --output text

See: InvalidInstanceId: An error occurred (InvalidInstanceId) when calling the SendCommand operation.

kenorb
  • 155,785
  • 88
  • 678
  • 743
Kush Vyas
  • 5,813
  • 2
  • 26
  • 36
0

I was able to create a script with Python using Boto3.

import boto3
import botocore
import paramiko

tagkey = 'Environment'
tagvalue = 'DEV'

# list_instances functions returns a list of ip addresses containing a set of tags
def list_instances(tagkey, tagvalue):

    ec2client = boto3.client('ec2')

    response = ec2client.describe_instances(
        Filters=[
            {
                'Name': 'tag:'+tagkey,
                'Values': [tagvalue]
            }
       ]
    )
    instancelist = []
    for reservation in (response["Reservations"]):
        for instance in reservation["Instances"]:
            instancelist.append(instance["PublicDnsName"])
    return instancelist

# Results of the function get stored in a list.
list = list_instances(tagkey, tagvalue)

key = paramiko.RSAKey.from_private_key_file("/home/ec2-user/key.pem")
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# Looping through all the instannces in the list
for instance_ip in list[:]:
                # Connect/ssh to an instance
    try:
                # Here 'ec2-user' is user name and 'instance_ip' is public IP of EC2
                client.connect(hostname=instance_ip, username="ec2-user", pkey=key)

                # Execute a command after connecting/ssh to an instance
                stdin, stdout, stderr = client.exec_command("touch test")

                # close the client connection once the job is done
                print "Command sent:",instance_ip

    except Exception, e:
        print e