473

How can I find out the instance id of an ec2 instance from within the ec2 instance?

37 Answers 37

645
Answer recommended by AWS Collective

See the EC2 documentation on the subject.

Run:

wget -q -O - http://169.254.169.254/latest/meta-data/instance-id

If you need programmatic access to the instance ID from within a script,

die() { status=$1; shift; echo "FATAL: $*"; exit $status; }
EC2_INSTANCE_ID="`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id || die \"wget instance-id has failed: $?\"`"

Here is an example of a more advanced use (retrieve instance ID as well as availability zone and region, etc.):

EC2_INSTANCE_ID="`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id || die \"wget instance-id has failed: $?\"`"
test -n "$EC2_INSTANCE_ID" || die 'cannot obtain instance-id'
EC2_AVAIL_ZONE="`wget -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone || die \"wget availability-zone has failed: $?\"`"
test -n "$EC2_AVAIL_ZONE" || die 'cannot obtain availability-zone'
EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed -e 's:\([0-9][0-9]*\)[a-z]*\$:\\1:'`"

You may also use curl instead of wget, depending on what is installed on your platform.

10
  • 2
    What about in the Java SDK? Is there any way to get this without having to do a GET on that url? Seems strange if it's not in the SDK
    – Kevin M
    Commented Aug 28, 2013 at 15:12
  • 1
    Very helpful, thanks. For others trying to figure out the regular expression in the last line, here's what I came up with: At the end of the line ($), find one or more digits following by one or more lowercase letters. Substitute with the digits only. (Backslash + parentheses tell sed to remember a substring, which is recalled with \1.) I found this a little easier to read--the only backslashes are those required by sed: EC2_REGION="$(echo "$EC2_AVAIL_ZONE" | sed -e 's:\([0-9][0-9]*\)[a-z]*$:\1:')".
    – Mark Berry
    Commented Jul 29, 2014 at 15:43
  • 89
    You can eliminate the magic numbers by using http://instance-data/ instead of 169.254.169.254
    – Jay Prall
    Commented Jan 6, 2015 at 17:12
  • 26
    I checked this on 2016-02-04. I found that the "instance-data" hostname is (a) not listed in that documentation, and (b) does not work (for me) on a new EC2 host. The documentation -- docs.aws.amazon.com/AWSEC2/latest/UserGuide/… -- only mentions the 169.254 address, and makes no mention of the "instance-data" hostname. i.e. use 169.254.169.254/latest/meta-data/instance-id
    – JDS
    Commented Feb 4, 2016 at 17:08
  • 3
    instance-data will only be available if you're using the Amazon DNS resolvers - if you're not, it won't be available. It resolves to 169.254.169.254.
    – mjturner
    Commented Dec 8, 2018 at 10:56
215

On Amazon Linux AMIs you can do:

$ ec2-metadata -i
instance-id: i-1234567890abcdef0

Or, on Ubuntu and some other linux flavours, ec2metadata --instance-id (This command may not be installed by default on ubuntu, but you can add it with sudo apt-get install cloud-utils)

As its name suggests, you can use the command to get other useful metadata too.

8
  • @Marc Nope. No - after ec2. It is ec2metadata --instance-id
    – Dawny33
    Commented Jan 29, 2018 at 9:22
  • 8
    The command is different on different Linuxes: on Amazon Linux it's ec2-metadata, on Ubuntu it seems to be ec2metadata.
    – James
    Commented Jan 29, 2018 at 13:04
  • 1
    @Cerin nope, this command is still the correct one on Amazon Linux 2. [ec2-user@ip-10-1-1-1 ~]$ ec2-metadata -i \ instance-id: <redacted> \ [ec2-user@ip-10-1-1-1 ~]$ ec2metadata \ -bash: ec2metadata: command not found
    – James
    Commented Aug 15, 2019 at 20:02
  • 1
    @Cerin perhaps you are using a different Linux distribution? This command is on Amazon Linux.
    – James
    Commented Aug 17, 2019 at 9:39
  • 2
    Things have changed since @James' comment (8 years ago); the ec2-metadata command is a shell script, not a Java program. Since the hypervisor's IMDS capabilities have been built out considerably, the only tool needed under the hood is wget or curl or similar.
    – Ti Strga
    Commented May 4, 2022 at 17:52
83

On Ubuntu you can:

sudo apt-get install cloud-utils

And then you can:

EC2_INSTANCE_ID=$(ec2metadata --instance-id)

You can get most of the metadata associated with the instance this way:

ec2metadata --help
Syntax: /usr/bin/ec2metadata [options]

Query and display EC2 metadata.

If no options are provided, all options will be displayed

Options:
    -h --help               show this help

    --kernel-id             display the kernel id
    --ramdisk-id            display the ramdisk id
    --reservation-id        display the reservation id

    --ami-id                display the ami id
    --ami-launch-index      display the ami launch index
    --ami-manifest-path     display the ami manifest path
    --ancestor-ami-ids      display the ami ancestor id
    --product-codes         display the ami associated product codes
    --availability-zone     display the ami placement zone

    --instance-id           display the instance id
    --instance-type         display the instance type

    --local-hostname        display the local hostname
    --public-hostname       display the public hostname

    --local-ipv4            display the local ipv4 ip address
    --public-ipv4           display the public ipv4 ip address

    --block-device-mapping  display the block device id
    --security-groups       display the security groups

    --mac                   display the instance mac address
    --profile               display the instance profile
    --instance-action       display the instance-action

    --public-keys           display the openssh public keys
    --user-data             display the user data (not actually metadata)
3
  • Under Ubuntu lucid apt-get install retrieves version 0.11-0ubuntu1 which doesn't contain this utility. It was added to the package just afterwards. Commented Jul 20, 2012 at 4:25
  • 7
    The cloud-utils package is included by default on the Ubuntu 12.04.1 LTS Cluster Compute AMI.
    – Andrew
    Commented Dec 13, 2012 at 22:11
  • 2
    cloud-utils seems to be in RHEL/CentOS too Commented May 16, 2013 at 6:47
67

Use the /dynamic/instance-identity/document URL if you also need to query more than just your instance ID.

wget -q -O - http://169.254.169.254/latest/dynamic/instance-identity/document

This will get you JSON data such as this - with only a single request.

{
    "devpayProductCodes" : null,
    "privateIp" : "10.1.2.3",
    "region" : "us-east-1",
    "kernelId" : "aki-12345678",
    "ramdiskId" : null,
    "availabilityZone" : "us-east-1a",
    "accountId" : "123456789abc",
    "version" : "2010-08-31",
    "instanceId" : "i-12345678",
    "billingProducts" : null,
    "architecture" : "x86_64",
    "imageId" : "ami-12345678",
    "pendingTime" : "2014-01-23T45:01:23Z",
    "instanceType" : "m1.small"
}
2
  • 2
    +1 for showing all details including instanceType in one simple call
    – Luksurious
    Commented Jun 2, 2014 at 15:22
  • 1
    +1 for having a fairly standard (wget only) and working line (instance-data url did not work for me on amazon linux), without installing additional packages just for this simple task.
    – tishma
    Commented Jan 11, 2016 at 12:46
54

For all ec2 machines, the instance-id can be found in file:

    /var/lib/cloud/data/instance-id

You can also get instance id by running the following command:

    ec2metadata --instance-id
7
  • 8
    This is a very clean solution, not requiring a HTTP request.
    – Yuri
    Commented Mar 28, 2018 at 6:19
  • The best possible answer actually
    – Shlublu
    Commented Oct 24, 2018 at 20:52
  • 2
    Great answer but I couldn't find a reference for this in the documentation. may I ask what your reference is? The concern is that if we are going to run this code in production, how do we know it won't change in the future? Commented Oct 25, 2018 at 6:57
  • 2
    All linux ec2 machines, perhaps, but definitely not all ec2 machines. No such file on Windows. C:\ProgramData\Amazon\EC2-Windows\Launch\Log\Ec2Launch.log contains the instance Id, but also has a whole lot of other junk.
    – James
    Commented Sep 11, 2019 at 22:19
  • cat the first command. This is the most simple and straightforward solution Commented May 2, 2023 at 18:09
46

on AWS Linux:

ec2-metadata --instance-id | cut -d " " -f 2

Output:

i-33400429

Using in variables:

ec2InstanceId=$(ec2-metadata --instance-id | cut -d " " -f 2);
ls "log/${ec2InstanceId}/";
2
  • Clean and concise way. Working out of the box for an instance with Ubuntu 14.
    – berbt
    Commented Jun 23, 2014 at 9:32
  • This works for instances in private subnets!
    – headz68
    Commented Apr 4 at 0:37
27

For .NET People :

string instanceId = new StreamReader(
      HttpWebRequest.Create("http://169.254.169.254/latest/meta-data/instance-id")
      .GetResponse().GetResponseStream())
    .ReadToEnd();
26

For powershell people:

(New-Object System.Net.WebClient).DownloadString("http://169.254.169.254/latest/meta-data/instance-id")
2
  • 4
    just different commandet: $instanceId=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id').Content Commented May 13, 2016 at 7:45
  • Invoke-WebRequest doesn't always work when running a script on said EC2 instance with a ssm send-command (or Send-SSMCommand). It doesn't really say in the docs. Possibly a it is not async... which would be weird. But stefancaunter's option works with no problems so far.
    – J-Roel
    Commented Aug 25, 2017 at 16:32
23

For Python:

import boto.utils
region=boto.utils.get_instance_metadata()['local-hostname'].split('.')[1]

which boils down to the one-liner:

python -c "import boto.utils; print boto.utils.get_instance_metadata()['local-hostname'].split('.')[1]"

Instead of local_hostname you could also use public_hostname, or:

boto.utils.get_instance_metadata()['placement']['availability-zone'][:-1]
4
  • All the newer versions of boto I see let you call the key "instance_id" directly. I made the relevant suggested edits.
    – saccharine
    Commented Aug 1, 2013 at 18:47
  • 8
    inst_id = boto.utils.get_instance_metadata()['instance-id']
    – atisman
    Commented Jun 3, 2014 at 2:01
  • You do realise this gets the region that the instance is in, not the instance-id as the question asked for, right?
    – LukeGT
    Commented May 27, 2015 at 6:42
  • 3
    For anyone wondering, this is in boto but is not yet in boto3. See stackoverflow.com/a/33733852 for a workaround using urllib. There's an open feature request at github.com/boto/boto3/issues/313 FWIW, the JS SDK also has this: docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/… Use new AWS.MetadataService().request('instance-id',function(error,data) { myInstanceId = data; }) Commented Feb 5, 2016 at 18:13
14

See this post - note that the IP address in the URL given is constant (which confused me at first), but the data returned is specific to your instance.

2
  • Link is 404ing for me Commented Mar 29, 2020 at 18:00
  • Check @DEtDev's answer below; my answer is pretty old and it looks like the link has been taken down. Commented Apr 3, 2020 at 0:13
13

Just Type:

ec2metadata --instance-id
4
  • which AMI you are using ?
    – Akash Arya
    Commented Feb 23, 2016 at 4:45
  • 4
    Apparently thats a command for the Amazon AMI, you should update your answer Commented Feb 23, 2016 at 12:06
  • @WédneyYuri Yes.
    – Akash Arya
    Commented May 28, 2018 at 7:26
  • For an alinux2 ami I have the ec2-metadata command not ec2metadata. Unsure if this is a typo or the command has changed in the new AMI instance. ec2-metadata --instance-id | cut -d' ' -f2 for just the id as a string Commented Aug 26, 2020 at 11:57
11

A more contemporary solution.

From Amazon Linux the ec2-metadata command is already installed.

From the terminal

ec2-metadata -help

Will give you the available options

ec2-metadata -i

will return

instance-id: yourid
3
  • 1
    much better than depending on the pseudo ip
    – Mike D
    Commented Jun 25, 2015 at 13:08
  • combine ec2-metadata with your motd, docs here: coderwall.com/p/hr_9pw/motds-on-amazon-amis
    – Mike D
    Commented Jun 25, 2015 at 13:10
  • 3
    In Ubuntu image the command is "ec2metadata --instance-id" and will return only the instance id value Commented Mar 4, 2016 at 15:02
10

You can try this:

#!/bin/bash
aws_instance=$(wget -q -O- http://169.254.169.254/latest/meta-data/instance-id)
aws_region=$(wget -q -O- http://169.254.169.254/latest/meta-data/hostname)
aws_region=${aws_region#*.}
aws_region=${aws_region%%.*}
aws_zone=`ec2-describe-instances $aws_instance --region $aws_region`
aws_zone=`expr match "$aws_zone" ".*\($aws_region[a-z]\)"`
10

For Ruby:

require 'rubygems'
require 'aws-sdk'
require 'net/http'

metadata_endpoint = 'http://169.254.169.254/latest/meta-data/'
instance_id = Net::HTTP.get( URI.parse( metadata_endpoint + 'instance-id' ) )

ec2 = AWS::EC2.new()
instance = ec2.instances[instance_id]
2
10

The latest Java SDK has EC2MetadataUtils:

In Java:

import com.amazonaws.util.EC2MetadataUtils;
String myId = EC2MetadataUtils.getInstanceId();

In Scala:

import com.amazonaws.util.EC2MetadataUtils
val myid = EC2MetadataUtils.getInstanceId
0
8

A c# .net class I wrote for EC2 metadata from the http api. I will build it up with functionality as needed. You can run with it if you like it.

using Amazon;
using System.Net;

namespace AT.AWS
{
    public static class HttpMetaDataAPI
    {
        public static bool TryGetPublicIP(out string publicIP)
        {
            return TryGetMetaData("public-ipv4", out publicIP);
        }
        public static bool TryGetPrivateIP(out string privateIP)
        {
            return TryGetMetaData("local-ipv4", out privateIP);
        }
        public static bool TryGetAvailabilityZone(out string availabilityZone)
        {
            return TryGetMetaData("placement/availability-zone", out availabilityZone);
        }

        /// <summary>
        /// Gets the url of a given AWS service, according to the name of the required service and the AWS Region that this machine is in
        /// </summary>
        /// <param name="serviceName">The service we are seeking (such as ec2, rds etc)</param>
        /// <remarks>Each AWS service has a different endpoint url for each region</remarks>
        /// <returns>True if the operation was succesful, otherwise false</returns>
        public static bool TryGetServiceEndpointUrl(string serviceName, out string serviceEndpointStringUrl)
        {
            // start by figuring out what region this instance is in.
            RegionEndpoint endpoint;
            if (TryGetRegionEndpoint(out endpoint))
            {
                // now that we know the region, we can get details about the requested service in that region
                var details = endpoint.GetEndpointForService(serviceName);
                serviceEndpointStringUrl = (details.HTTPS ? "https://" : "http://") + details.Hostname;
                return true;
            }
            // satisfy the compiler by assigning a value to serviceEndpointStringUrl
            serviceEndpointStringUrl = null;
            return false;
        }
        public static bool TryGetRegionEndpoint(out RegionEndpoint endpoint)
        {
            // we can get figure out the region end point from the availability zone
            // that this instance is in, so we start by getting the availability zone:
            string availabilityZone;
            if (TryGetAvailabilityZone(out availabilityZone))
            {
                // name of the availability zone is <nameOfRegionEndpoint>[a|b|c etc]
                // so just take the name of the availability zone and chop off the last letter
                var nameOfRegionEndpoint = availabilityZone.Substring(0, availabilityZone.Length - 1);
                endpoint = RegionEndpoint.GetBySystemName(nameOfRegionEndpoint);
                return true;
            }
            // satisfy the compiler by assigning a value to endpoint
            endpoint = RegionEndpoint.USWest2;
            return false;
        }
        /// <summary>
        /// Downloads instance metadata
        /// </summary>
        /// <returns>True if the operation was successful, false otherwise</returns>
        /// <remarks>The operation will be unsuccessful if the machine running this code is not an AWS EC2 machine.</remarks>
        static bool TryGetMetaData(string name, out string result)
        {
            result = null;
            try { result = new WebClient().DownloadString("http://169.254.169.254/latest/meta-data/" + name); return true; }
            catch { return false; }
        }

/************************************************************
 * MetaData keys.
 *   Use these keys to write more functions as you need them
 * **********************************************************
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
hostname
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
*************************************************************/
    }
}
7

Simply check the var/lib/cloud/instance symlink, it should point to /var/lib/cloud/instances/{instance-id} where {instance_id} is your instance-id.

2
  • 1
    I would not use this. You are better off using the approved HTTP request to get the metadata. Commented Nov 6, 2018 at 14:43
  • This worked for me. Thank you so much - piece of cake. Commented Apr 22 at 20:42
6

Simple one line

cat /sys/devices/virtual/dmi/id/board_asset_tag

or

curl_cli -s http://169.254.169.254/latest/meta-data/instance-id

source: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html

1
  • I like that this method doesn't assume metadata service access is enabled for the instance (not best practice for security), and still has some level of official documentation (for instances based on the nitro hypervisor).
    – benjimin
    Commented Apr 10, 2023 at 4:39
5

For C++ (using cURL):

    #include <curl/curl.h>

    //// cURL to string
    size_t curl_to_str(void *contents, size_t size, size_t nmemb, void *userp) {
        ((std::string*)userp)->append((char*)contents, size * nmemb);
        return size * nmemb;
    };

    //// Read Instance-id 
    curl_global_init(CURL_GLOBAL_ALL); // Initialize cURL
    CURL *curl; // cURL handler
    CURLcode res_code; // Result
    string response;
    curl = curl_easy_init(); // Initialize handler
    curl_easy_setopt(curl, CURLOPT_URL, "http://169.254.169.254/latest/meta-data/instance-id");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_to_str);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
    res_code = curl_easy_perform(curl); // Perform cURL
    if (res_code != CURLE_OK) { }; // Error
    curl_easy_cleanup(curl); // Cleanup handler
    curl_global_cleanup(); // Cleanup cURL
4

If you wish to get the all instances id list in python here is the code:

import boto3

ec2=boto3.client('ec2')
instance_information = ec2.describe_instances()

for reservation in instance_information['Reservations']:
   for instance in reservation['Instances']:
      print(instance['InstanceId'])
3

In Go you can use the goamz package.

import (
    "github.com/mitchellh/goamz/aws"
    "log"
)

func getId() (id string) {
    idBytes, err := aws.GetMetaData("instance-id")
    if err != nil {
        log.Fatalf("Error getting instance-id: %v.", err)
    }

    id = string(idBytes)

    return id
}

Here's the GetMetaData source.

3

You can just make a HTTP request to GET any Metadata by passing the your metadata parameters.

curl http://169.254.169.254/latest/meta-data/instance-id

or

wget -q -O - http://169.254.169.254/latest/meta-data/instance-id

You won't be billed for HTTP requests to get Metadata and Userdata.

Else

You can use EC2 Instance Metadata Query Tool which is a simple bash script that uses curl to query the EC2 instance Metadata from within a running EC2 instance as mentioned in documentation.

Download the tool:

$ wget http://s3.amazonaws.com/ec2metadata/ec2-metadata

now run command to get required data.

$ec2metadata -i

Refer:

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

https://aws.amazon.com/items/1825?externalID=1825

Happy To Help.. :)

3

FWIW I wrote a FUSE filesystem to provide access to the EC2 metadata service: https://github.com/xdgc/ec2mdfs . I run this on all custom AMIs; it allows me to use this idiom: cat /ec2/meta-data/ami-id

0
2

Motivation: User would like to Retrieve aws instance metadata.

Solution: The IP address 169.254.169.254 is a link-local address (and is valid only from the instance) aws gives us link with dedicated Restful API for Retrieving metadata of our running instance (Note that you are not billed for HTTP requests used to retrieve instance metadata and user data) . for Additional Documentation

Example:

//Request:
curl http://169.254.169.254/latest/meta-data/instance-id

//Response
ami-123abc

You able to get additional metadata labels of your instance using this link http://169.254.169.254/latest/meta-data/<metadata-field> just choose the right tags:

  1. ami-id
  2. ami-launch-index
  3. ami-manifest-path
  4. block-device
  5. mapping
  6. events
  7. hibernation
  8. hostname
  9. iam
  10. identity-credentials
  11. instance-action
  12. instance-id
  13. instance-type
  14. local-hostname
  15. local-ipv4
  16. mac
  17. metrics
  18. network
  19. placement
  20. profile
  21. reservation-id
  22. security-groups
  23. services
2
  • curl: (7) Failed to connect to IP port 80: Connection refuse , Port 80 is open
    – CodeGuru
    Commented Jun 7, 2021 at 14:51
  • For an up-to-date list, curl at the parent level: http://169.254.169.254/latest/meta-data/
    – Akom
    Commented May 4, 2022 at 19:00
2

Most simple approach is to use aws cli and sts get-caller-identity.

INSTANCE_ID=$(aws sts get-caller-identity --query UserId --output text | cut -d : -f 2)

  • This way you don't need to authorize against metadata endpoint manually.
  • It works on any unix AMI in contrast to ec2-metadata command that is only available for amazon linux AMIs
1

In the question you have mentioned the user as root, one thing I should mention is that the instance ID is not dependent on the user.

For Node developers,

var meta  = new AWS.MetadataService();

meta.request("/latest/meta-data/instance-id", function(err, data){
    console.log(data);
});
1

To get the instance metadata use

wget -q -O - http://169.254.169.254/latest/meta-data/instance-id
1

For a Windows instance:

(wget http://169.254.169.254/latest/meta-data/instance-id).Content

or

(ConvertFrom-Json (wget http://169.254.169.254/latest/dynamic/instance-identity/document).Content).instanceId
1
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` 

AMI=`curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/ami-id`

echo $AMI

This should helps you,

0

Alternative approach for PHP:

$instance = json_decode(file_get_contents('http://169.254.169.254/latest/dynamic/instance-identity/document'),true);
$id = $instance['instanceId'];
print_r($instance);

That will provide a lot of data about the instance, all nicely packed in an array, no external dependencies. As it's a request that never failed or delayed for me it should be safe to do it that way, otherwise I'd go for curl()

Not the answer you're looking for? Browse other questions tagged or ask your own question.