阿里云ECS资源监控脚本
阿里云ECS实例资源监控脚本,使用阿里云CLI查询CPU/内存/磁盘/网络使用率,识别闲置实例,支持成本优化建议
详细内容
#!/bin/bash
# 阿里云ECS资源监控与成本优化脚本
# 需要安装阿里云CLI并配置AccessKey
# 安装: pip install aliyun-cli 或 下载官方CLI
REGION="cn-hangzhou"
ACCESS_KEY_ID="your_access_key_id"
ACCESS_KEY_SECRET="your_access_key_secret"
CPU_THRESHOLD=20 # CPU低于此值视为闲置
DISK_THRESHOLD=30 # 磁盘使用率低于此值视为浪费
LOG_FILE="/var/log/aliyun_ecs_monitor.log"
REPORT_FILE="/tmp/aliyun_ecs_report_$(date +%Y%m%d).txt"
log_msg() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" "$REPORT_FILE"
}
log_msg "===== 阿里云ECS资源监控 ====="
log_msg "区域: $REGION"
log_msg "时间: $(date '+%Y-%m-%d %H:%M:%S')"
# 检查阿里云CLI
if ! command -v aliyun >/dev/null 2>&1; then
log_msg "❌ 阿里云CLI未安装"
log_msg "安装方法: https://help.aliyun.com/document_detail/139508.html"
exit 1
fi
# 配置凭证
export ALIBABA_CLOUD_ACCESS_KEY_ID=$ACCESS_KEY_ID
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=$ACCESS_KEY_SECRET
# 1. 获取ECS实例列表
log_msg ""
log_msg "【1. ECS实例列表】"
INSTANCES=$(aliyun ecs DescribeInstances --RegionId $REGION --output cols=InstanceId,InstanceName,Status,InstanceType,PublicIpAddress 2>/dev/null)
if [ -z "$INSTANCES" ]; then
log_msg " 无ECS实例或查询失败"
exit 0
fi
echo "$INSTANCES" | while read line; do
log_msg " $line"
done
INSTANCE_COUNT=$(echo "$INSTANCES" | wc -l)
log_msg " 实例总数: $INSTANCE_COUNT"
# 2. 获取监控数据(最近1小时平均CPU)
log_msg ""
log_msg "【2. 资源使用率分析(最近1小时)】"
log_msg " 正在获取云监控数据..."
# 获取实例ID列表
INSTANCE_IDS=$(aliyun ecs DescribeInstances --RegionId $REGION --output cols=InstanceId 2>/dev/null | tail -n +2)
IDLE_COUNT=0
TOTAL_COST=0
for instance_id in $INSTANCE_IDS; do
# 获取CPU平均使用率
CPU_AVG=$(aliyun cms DescribeMetricLast --Namespace acs_ecs_dashboard --MetricName cpu_total --Period 3600 --Dimensions "[{"instanceId":"$instance_id"}]" --output cols=Average 2>/dev/null | tail -1)
# 获取实例名称
INSTANCE_NAME=$(aliyun ecs DescribeInstanceAttribute --InstanceId $instance_id --output cols=InstanceName 2>/dev/null | tail -1)
# 获取实例规格和价格估算
INSTANCE_TYPE=$(aliyun ecs DescribeInstanceAttribute --InstanceId $instance_id --output cols=InstanceType 2>/dev/null | tail -1)
CPU_VAL=$(echo "$CPU_AVG" | grep -oE '[0-9.]+' | head -1)
CPU_VAL=${CPU_VAL:-0}
if (( $(echo "$CPU_VAL < $CPU_THRESHOLD" | bc -l) )); then
log_msg " ⚠️ 闲置实例: $INSTANCE_NAME ($instance_id)"
log_msg " CPU: ${CPU_VAL}% (低于阈值${CPU_THRESHOLD}%)"
log_msg " 规格: $INSTANCE_TYPE"
IDLE_COUNT=$((IDLE_COUNT + 1))
else
log_msg " ✓ $INSTANCE_NAME: CPU ${CPU_VAL}%"
fi
done
# 3. 磁盘使用分析
log_msg ""
log_msg "【3. 磁盘使用分析】"
DISKS=$(aliyun ecs DescribeDisks --RegionId $REGION --output cols=DiskId,Size,Category,Status 2>/dev/null)
echo "$DISKS" | while read line; do
log_msg " $line"
done
# 4. 成本优化建议
log_msg ""
log_msg "【4. 成本优化建议】"
if [ "$IDLE_COUNT" -gt 0 ]; then
log_msg " 🔴 发现 $IDLE_COUNT 台闲置实例,建议:"
log_msg " 1. 降配:降低实例规格,节省费用"
log_msg " 2. 释放:确认无用后释放实例"
log_msg " 3. 转包年包月:长期使用的实例转预付费更便宜"
else
log_msg " ✅ 无明显闲置实例"
fi
log_msg ""
log_msg " 其他优化建议:"
log_msg " - 检查是否有未挂载的磁盘(浪费费用)"
log_msg " - 检查弹性公网IP是否有闲置"
log_msg " - 考虑使用抢占式实例降低成本"
log_msg " - 设置自动伸缩,按需扩缩容"
# 5. 安全组检查
log_msg ""
log_msg "【5. 安全组风险检查】"
SECURITY_GROUPS=$(aliyun ecs DescribeSecurityGroups --RegionId $REGION --output cols=SecurityGroupId,SecurityGroupName 2>/dev/null)
echo "$SECURITY_GROUPS" | while read line; do
sg_id=$(echo "$line" | awk '{print $1}')
if [ -n "$sg_id" ]; then
# 检查是否有0.0.0.0/0开放高危端口
RISK=$(aliyun ecs DescribeSecurityGroupAttribute --SecurityGroupId $sg_id --output cols=SourceCidrIp,IpProtocol,PortRange 2>/dev/null | grep -E "0.0.0.0/0.*(22|3306|6379|27017|1433)")
if [ -n "$RISK" ]; then
log_msg " ⚠️ 安全组 $sg_id 存在高危端口对外开放:"
echo "$RISK" | while read r; do
log_msg " $r"
done
fi
fi
done
log_msg ""
log_msg "===== 监控完成 ====="
log_msg "报告已保存到: $REPORT_FILE"
适配环境
适配系统:CentOS 7+,Ubuntu 18.04+,Debian 10+
依赖环境:bash 4.0+
参数说明
[{"name": "REGION", "label": "\u963f\u91cc\u4e91\u533a\u57df", "default": "cn-hangzhou"}, {"name": "ACCESS_KEY_ID", "label": "AccessKey ID", "default": "your_access_key_id"}, {"name": "ACCESS_KEY_SECRET", "label": "AccessKey Secret", "default": "your_access_key_secret"}, {"name": "CPU_THRESHOLD", "label": "\u95f2\u7f6eCPU\u9608\u503c(%)", "default": "20"}]