1. Introduction

Although Amazon provides a graphical user interface (GUI) for convenience, we can also employ a command line interface (CLI) for the same purpose. The latter is usually better when automating activities.

In this short tutorial, we’re going to take a look at the AWS Command Line Interface for EC2 services.

Before going further, let’s remember to configure the AWS CLI access.

2. List EC2 Instances

First, we explore how to list all current EC2 instances:

$ aws ec2 describe-instances

The output contains all necessary data about the instances in a JSON format.

Let’s look at some useful properties:

$ aws ec2 describe-instances
...
{
  "InstanceId": "instance_id",
  "InstanceType": "t2.small",
  "KeyName": "ssh_key_name",
  "LaunchTime": "2020-01-31T15:48:22.000Z",
  "Monitoring": {
    "State": "disabled"
  },
  "Placement": {
    "AvailabilityZone": "eu-central-1c"
  },
  "PublicIpAddress": "1.123.123.12",
  "State": {
    "Code": 80,
    "Name": "stopped"
  },
  "Tags": [
    {
      "Key": "Creator",
      "Value": "Baeldung"
    }
  ]
}

Further, we can leverage the CLI to filter the instances by a given property. To do so, we need to add an extra –filters parameter.

For example, let’s search for instances with a given type:

$ aws ec2 describe-instances --filters Name=instance-type,Values=t2.medium

Now, we can use a tag key:

$ aws ec2 describe-instances --filters "Name=tag-key,Values=Baeldung"

Both return only the instances that match the respective filters.

To get details about specific EC2 instances, we pass the –instance-ids parameter followed by a list of instance IDs:

$ aws ec2 describe-instances --instance-ids instance_id instance_id_2

This way, we only see data according to the selection.

3. Create a New Key Pair for EC2 Instances

Before launching a new EC2 instance, we generate an SSH key pair to use for the connection.

The AWS CLI provides a fairly easy way for key generation:

$ aws ec2 create-key-pair --key-name BaeldungKey --output text > BaeldungKey.pem

Specifically, the above command creates a new key in the AWS named BaeldungKey and pipes the secret key directly to the location we specify, in this case, BaeldungKey.pem.

The format of the resulting file is typical:

-----BEGIN RSA PRIVATE KEY-----
EXAMPLEKEYKCAQEAy7WZhaDsrA1W3mRlQtvhwyO
...
-----END RSA PRIVATE KEY-----

Now, we can use it while creating a new EC2 instance.

4. Launch New EC2 Instances

The AWS CLI also provides a convenient way to launch new EC2 instances. As a prerequisite, we prepare a pem key pair by name and choose the desired Amazon Machine Image (AMI) and instance type.

The AMI provides the operating system (OS), application server, and applications for the instance. To be clear, the instance type defines hardware properties like CPU and RAM.

As an example, we create t2.micro instance running Ubuntu 18.04 image with an ID of ami-0b418580298265d5c:

$ aws ec2 run-instances --image-id ami-0b418580298265d5c --instance-type t2.micro --key-name BaeldungKey

As we can see, the run-instances command is the main way to launch instances.

Its output contains all the new instance data in a JSON format:

$ aws ec2 run-instances --image-id ami-0b418580298265d5c --instance-type t2.micro --key-name BaeldungKey
[...]
{
  "Instances": [
    {
      "PrivateDns": "ip-10-31-39-158.eu-central-1.compute.internal",
      "Status": "booting",
      "InstanceId": "9b137a0d-2f5d-4cc0-9704-13da4b31fdcb",
      "SshKeyName": "EU-Central-1",
      "InstanceType": "t2.micro",
      "CreatedAt": "2020-02-07T11:00:00+00:00",
      "PublicDns": "ec2-192-0-2-1.eu-central-1.compute.amazonaws.com",
      "SecurityGroupIds": [
        "sg-b022add5"
      ],
      "Architecture": "x86_64",
      "RootDeviceType": "ebs",
      "Os": "Server Ubuntu 18.04",
      "AvailabilityZone": "eu-central-1c",
      "PrivateIp": "10.31.39.158",
      "PublicIp": "192.0.2.0"
    }
  ]
}

After launching the new instance, it’s ready for use. To connect to it, we can either use its IP address from the PublicIp property or a host from the PublicDns property.

Critically, there might be a short time before we can connect to it. This can be monitored by the instance state found in the describe-instances command output.

Initially, the instance state is pending:

{
  ...
  "State": {
    "Code": 0,
    "Name": "pending"
  },
  ...
}

When the state is running, the instance is fully booted and ready to connect to:

{
  ...
  "State": {
    "Code": 16,
    "Name": "running"
  },
  ...
}

While creating a new instance, we can specify a security group that gets attached to it by adding the –security-group-ids security_group_id parameter. If we don’t specify such a group, the default one is used.

We can also specify the subnet ID by just adding –subnet-id subnet_id. Again, the default one gets applied in case we don’t use the option.

5. Stop and Start an EC2 Instance

In addition, any on-demand EC2 instance in a running state can be stopped:

$ aws ec2 stop-instances --instance-ids instance_id

Conversely, we can also start it again:

$ aws ec2 start-instances --instance-ids instance_id

Notably, although instances retain their identifiers after startup, they get a different public IP address.

6. Terminate an EC2 Instance

If we want to remove an instance completely, then we can terminate it:

$ aws ec2 terminate-instances --instance-ids instance_id

Critically, when we terminate an instance it won’t be possible to start it again like with a stopped instance. The reason behind this lies in the instance lifecycle.

Terminated instances remain visible after termination for approximately one hour.

7. Run Commands Within EC2 Instance

While AWS offers different ways to configure instances, we might want to perform further setup once the instance is up. For this reason, having a way to run commands directly within the resulting instance can be advantageous.

To that end, once we have an instance up and running, we can use the ssm category with its send-command subcommand:

$ aws ssm send-command --document-name 'AWS-RunShellScript' --instance-ids instance-id --parameters commands=command --output text

Let’s break this down:

  • –document-name specifies the AWS-RunShellScript document for running local commands
  • –instance-ids uses the given instance identifiers as filters
  • –parameters commands= indicates the full command we want to run
  • –output is optional and can be json, text, or table

If desired, we can also add a –comment for a more specific description of the command.

Of course, how we supply the command varies according to the platform in question. In particular, if working with Microsoft Windows, we might want to consider the specifics of PowerShell.

One critical aspect of command execution via ssm send-command is the 2500-character limit on the output. To work around that, we can append the –output-s3-bucket-name option with a specific bucket name. As a result, the output is redirected and stored, so we can automate its parsing.

8. Conclusion

In this article, we’ve learned how to manage EC2 instances via the command line interface.

First, we generated an SSH access key for EC2 instances. Next, we listed and created new EC2 instances. Then, we saw how to start, stop, or terminate them. Finally, we considered a way to run commands within an instance OS environment via aws that mimics local runs.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.