ChatGPT解决这个技术问题 Extra ChatGPT

How to get the instance id from within an ec2 instance?

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


T
The-Big-K

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.


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
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:')".
You can eliminate the magic numbers by using http://instance-data/ instead of 169.254.169.254
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
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.
J
James

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.


The best answer
@Marc Nope. No - after ec2. It is ec2metadata --instance-id
The command is different on different Linuxes: on Amazon Linux it's ec2-metadata, on Ubuntu it seems to be ec2metadata.
@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
@Cerin perhaps you are using a different Linux distribution? This command is on Amazon Linux.
r
rhunwicks

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)

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.
The cloud-utils package is included by default on the Ubuntu 12.04.1 LTS Cluster Compute AMI.
cloud-utils seems to be in RHEL/CentOS too
c
chicks

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"
}

+1 for showing all details including instanceType in one simple call
+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.
g
gpupo

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}/";

Clean and concise way. Working out of the box for an instance with Ubuntu 14.
A
Aman

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

This is a very clean solution, not requiring a HTTP request.
The best possible answer actually
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?
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.
r
rae1

For .NET People :

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

T
Taryn

For powershell people:

(New-Object System.Net.WebClient).DownloadString("http://169.254.169.254/latest/meta-data/instance-id")

just different commandet: $instanceId=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id').Content
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.
b
benlast

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]

All the newer versions of boto I see let you call the key "instance_id" directly. I made the relevant suggested edits.
inst_id = boto.utils.get_instance_metadata()['instance-id']
You do realise this gets the region that the instance is in, not the instance-id as the question asked for, right?
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; })
g
gareth_bowles

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.


Link is 404ing for me
Check @DEtDev's answer below; my answer is pretty old and it looks like the link has been taken down.
A
Akash Arya

Just Type:

ec2metadata --instance-id

which AMI you are using ?
Apparently thats a command for the Amazon AMI, you should update your answer
@WédneyYuri Yes.
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
D
DetDev

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

much better than depending on the pseudo ip
combine ec2-metadata with your motd, docs here: coderwall.com/p/hr_9pw/motds-on-amazon-amis
In Ubuntu image the command is "ec2metadata --instance-id" and will return only the instance id value
A
Alex Koloskov

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]\)"`

K
Kevin Meyer

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]

WTF guys?! You stole my edit! stackoverflow.com/review/suggested-edits/4035074
Sorry. Didn't know how to say "It's a good edit. I'm the OP. Accept this".
M
Mattiavelli

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

b
bboyle1234

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
*************************************************************/
    }
}

M
Medical physicist

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

g
greg

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.


I would not use this. You are better off using the approved HTTP request to get the metadata.
V
Vikas Satpute

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'])

d
dmikalova

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.


c
codeforester

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.. :)


d
dgc

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


a
avivamg

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:

ami-id ami-launch-index ami-manifest-path block-device mapping events hibernation hostname iam identity-credentials instance-action instance-id instance-type local-hostname local-ipv4 mac metrics network placement profile reservation-id security-groups services


curl: (7) Failed to connect to IP port 80: Connection refuse , Port 80 is open
For an up-to-date list, curl at the parent level: http://169.254.169.254/latest/meta-data/
R
Rumesh Eranga Hapuarachchi

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);
});

i
iBug

To get the instance metadata use

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

d
demonicdaron

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

J
John

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()


B
Beachhouse

For PHP:

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

Edit per @John


But why would you use GuzzeHttp for that purpose if you have curl and native functions in PHP ?
It's my preference. I use guzzle for many other things, it is a common prerequisite for many other packages as well.
$instance = json_decode(file_get_contents('169.254.169.254/latest/dynamic/instance-identity/…); $id = $instance['instanceId']; I know Guzzle is widespread, I've never touched it myself. For such a simple task I'd provide the lightest approach.
C
Chinthaka Hasakelum

Run this:

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

You will be able to see different types of attributes which are provided by aws.

Use this link to view more


V
Vipin Sharma

All meta-data related to EC2 resource can be accessed by the EC2 instance itself with the help of the following command being executed:

CURL :

http://169.254.169.254/<api-version>/meta-data/<metadata-requested>

For your case: "metadata-requested" should be instance-id , "api-version" is usually latest that can be used.

Additional Note: You can also get information related to below EC2 attributes using the above command.

ami-id, ami-launch-index, ami-manifest-path, block-device-mapping/, hostname, iam/, 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, services/,

For more details please follow this link : https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html