3

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.

1

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

I've tried that command and I kept getting this error: "An error occurred (InvalidInstanceId) when calling the SendCommand operation"
What Error , please post or if it's bigger edit question accordingly
Updated the answer
You have to pass the instance ids as separate string values --instance-ids <id> <id> <id> etc.., not --instance-ids "<id> <id> <id>". Quoting the list of ids as shown here will pass them all as one string.
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.