You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Bash curl命令检查预定义IP的AWS EC2实例就绪状态(无需AWS CLI)

Alright, let's tackle this. You want to check if a remote AWS EC2 instance has passed both status checks (the "2/2 checks passed" you see in the AWS Console) using just bash and curl in cloud-init, no AWS CLI required. Here are two approaches depending on your exact needs:

Option 1: Strictly match AWS Console's status checks (2/2 passed)

This method calls the EC2 DescribeInstanceStatus API to verify both the Instance Status Check and System Status Check are marked as "ok". It requires AWS credentials (best provided via an IAM role attached to the cloud-init instance).

Step 1: Ensure IAM Permissions

First, make sure the instance running cloud-init has an IAM role with the ec2:DescribeInstanceStatus permission. This avoids hardcoding credentials in your script.

Step 2: Cloud-init Script

Add this to your cloud-init user data. It includes a simplified AWS V4 signature implementation for the API call, waits for the checks to pass, and times out after 5 minutes:

#!/bin/bash

# --------------------------
# Configuration Parameters
# --------------------------
REMOTE_INSTANCE_ID="i-1234567890abcdef0"  # Replace with your EC2 instance ID
AWS_REGION="us-east-1"                     # Replace with your instance's region
WAIT_TIMEOUT=300                           # Max wait time in seconds (5 mins)
WAIT_INTERVAL=10                           # Check every 10 seconds

# --------------------------
# Install Dependencies
# --------------------------
# For Ubuntu/Debian-based systems
apt-get update && apt-get install -y jq openssl libxml2-utils > /dev/null 2>&1

# For RHEL/CentOS-based systems (uncomment if needed)
# yum install -y jq openssl libxml2 > /dev/null 2>&1

# --------------------------
# Fetch AWS Credentials (from IAM Role)
# --------------------------
if [ -z "$AWS_ACCESS_KEY_ID" ]; then
    IAM_ROLE=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
    if [ -z "$IAM_ROLE" ]; then
        echo "Error: No IAM role attached and no AWS credentials provided."
        exit 1
    fi
    CREDS=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE)
    AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r '.AccessKeyId')
    AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r '.SecretAccessKey')
    AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r '.Token')
fi

# --------------------------
# AWS V4 Signature Helper
# --------------------------
aws_v4_sign() {
    local method=$1
    local url=$2
    local region=$3
    local service=$4
    local access_key=$5
    local secret_key=$6
    local session_token=$7

    local date=$(date -u +'%Y%m%dT%H%M%SZ')
    local date_short=$(date -u +'%Y%m%d')

    # Build canonical request
    local canonical_request="$method
$(echo "$url" | awk -F/ '{print $3}')
/$(echo "$url" | cut -d/ -f4- | sed 's/?.*//')
$(echo "$url" | cut -d? -f2 | tr '&' '\n' | sort | tr '\n' '&' | sed 's/&$//')
content-type:application/json
host:$(echo "$url" | awk -F/ '{print $3}')
x-amz-date:$date
x-amz-security-token:$session_token

content-type;host;x-amz-date;x-amz-security-token
$(echo -n '' | sha256sum | awk '{print $1}')"

    # Build string to sign
    local string_to_sign="AWS4-HMAC-SHA256
$date
$date_short/$region/$service/aws4_request
$(echo -n "$canonical_request" | sha256sum | awk '{print $1}')"

    # Generate signing keys
    local k_date=$(echo -n "$date_short" | openssl dgst -sha256 -hmac "AWS4$secret_key" -binary | xxd -p -c 256)
    local k_region=$(echo -n "$region" | openssl dgst -sha256 -hmac "$k_date" -binary | xxd -p -c 256)
    local k_service=$(echo -n "$service" | openssl dgst -sha256 -hmac "$k_region" -binary | xxd -p -c 256)
    local k_signing=$(echo -n "aws4_request" | openssl dgst -sha256 -hmac "$k_service" -binary | xxd -p -c 256)

    # Calculate final signature
    local signature=$(echo -n "$string_to_sign" | openssl dgst -sha256 -hmac "$k_signing" -binary | xxd -p -c 256)

    # Return Authorization header
    echo "AWS4-HMAC-SHA256 Credential=$access_key/$date_short/$region/$service/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, Signature=$signature"
}

# --------------------------
# Wait for Status Checks to Pass
# --------------------------
elapsed=0
while [ $elapsed -lt $WAIT_TIMEOUT ]; do
    # Build API request URL
    api_url="https://ec2.$AWS_REGION.amazonaws.com/?Action=DescribeInstanceStatus&InstanceIds.1=$REMOTE_INSTANCE_ID&Version=2016-11-15"

    # Generate auth header
    auth_header=$(aws_v4_sign "GET" "$api_url" "$AWS_REGION" "ec2" "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "$AWS_SESSION_TOKEN")

    # Send request and parse response
    response=$(curl -s -H "Content-Type: application/json" \
                   -H "X-Amz-Date: $(date -u +'%Y%m%dT%H%M%SZ')" \
                   -H "X-Amz-Security-Token: $AWS_SESSION_TOKEN" \
                   -H "Authorization: $auth_header" \
                   "$api_url")

    # Extract status values
    instance_status=$(echo "$response" | xmllint --xpath 'string(//InstanceStatus/InstanceStatus/Status)' -)
    system_status=$(echo "$response" | xmllint --xpath 'string(//InstanceStatus/SystemStatus/Status)' -)

    # Check if both are "ok"
    if [ "$instance_status" = "ok" ] && [ "$system_status" = "ok" ]; then
        echo "✅ Remote instance $REMOTE_INSTANCE_ID has passed both status checks (2/2)."
        exit 0
    fi

    echo "⏳ Waiting for instance $REMOTE_INSTANCE_ID... Current status: Instance=$instance_status, System=$system_status ($elapsed/$WAIT_TIMEOUT seconds)"
    sleep $WAIT_INTERVAL
    elapsed=$((elapsed + WAIT_INTERVAL))
done

echo "❌ Timeout: Remote instance $REMOTE_INSTANCE_ID did not pass both status checks within $WAIT_TIMEOUT seconds."
exit 1

Option 2: Simple Reachability Check (Faster, Less Strict)

If you just need to confirm the remote instance is accessible (e.g., SSH is open) instead of strictly matching AWS's status checks, this simpler script works. It uses nc (netcat) to check a specific port:

#!/bin/bash

REMOTE_IP="1.2.3.4"  # Replace with your instance's public/private IP
TARGET_PORT=22       # SSH port, or replace with your application port
WAIT_TIMEOUT=300     # 5 minute timeout
WAIT_INTERVAL=10     # Check every 10 seconds

# Install netcat if missing (Ubuntu/Debian)
apt-get update && apt-get install -y netcat > /dev/null 2>&1

elapsed=0
while [ $elapsed -lt $WAIT_TIMEOUT ]; do
    if nc -z $REMOTE_IP $TARGET_PORT; then
        echo "✅ Remote instance $REMOTE_IP is reachable on port $TARGET_PORT."
        exit 0
    fi
    echo "⏳ Waiting for instance $REMOTE_IP to become reachable... ($elapsed/$WAIT_TIMEOUT seconds)"
    sleep $WAIT_INTERVAL
    elapsed=$((elapsed + WAIT_INTERVAL))
done

echo "❌ Timeout: Remote instance $REMOTE_IP is not reachable on port $TARGET_PORT within $WAIT_TIMEOUT seconds."
exit 1

Key Notes:

  • Option 1 is the only way to strictly replicate the AWS Console's "2/2 checks passed" status, but it requires IAM permissions and handles API signing.
  • Option 2 is faster and simpler, but it only checks if a specific port is open (not the underlying AWS system/instance health checks).

内容的提问来源于stack exchange,提问作者ikask

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:28:44