阿里云-ECS实例信息统计并发送统计报告到企业微信

文章目录

免费个人运维知识库,欢迎您的订阅:literator_ray.flowus.cn

一、脚本功能描述

1. ​配置管理

  • 支持两种配置文件格式(.config.pyconfig.py

  • 优先使用隐藏配置文件.config.py

  • 需要配置阿里云访问密钥和企业微信Webhook

2. ​阿里云ECS监控

  • 区域监控​:专门监控北京区域的ECS实例

  • 分页查询​:自动处理分页,获取所有ECS实例

  • 实例信息收集​:获取实例ID、名称、IP地址、创建时间等关键信息

3. ​数据分析功能

  • 总量统计​:统计全部ECS服务器数量

  • 新增检测​:识别近1个月内新增的ECS实例

  • 时间格式处理​:支持多种时间格式解析,确保兼容性

4. ​企业微信集成

  • 消息推送​:将监控结果推送到企业微信机器人

  • 格式化输出​:生成清晰的表格格式报告

  • 错误通知​:执行过程中的错误也会发送到企业微信

可以根据自己的实际需求修改脚本

二、脚本内容

脚本共182行,动动你的小手滚动查看

Shell 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import json
import os
import argparse
from dotenv import load_dotenv  # 用于加载.env文件

# 检查并尝试导入所需模块
try:
    from aliyunsdkcore.client import AcsClient
    from aliyunsdkcore.acs_exception.exceptions import ClientException, ServerException
    from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest
except ImportError as e:
    print(f"导入模块失败: {e}")
    print("请确保已安装阿里云SDK: pip install aliyun-python-sdk-core aliyun-python-sdk-alidns")
    sys.exit(1)

# 加载.env文件(如果存在)
load_dotenv()

def split_domain(full_domain):
    """
    拆分完整域名为主域名和子域名部分
    例如: www.example.com -> (example.com, www)
          example.com -> (example.com, '@')
    """
    parts = full_domain.split('.')
    
    # 如果域名部分少于2,则无法拆分
    if len(parts) < 2:
        raise ValueError("无效的域名格式")
    
    # 尝试识别主域名(通常为最后两部分,但需要考虑如.co.uk的情况)
    # 这里使用简单策略:取最后两部分作为主域名
    domain = '.'.join(parts[-2:])
    subdomain = '.'.join(parts[:-2]) if len(parts) > 2 else '@'
    
    return domain, subdomain

def query_dns_records(access_key_id, access_key_secret, region_id, full_domain):
    """
    查询阿里云DNS记录
    """
    try:
        # 拆分域名
        domain, rr_keyword = split_domain(full_domain)
        print(f"查询域名: {domain}, 子域名: {rr_keyword}")
        
        # 创建AcsClient实例
        client = AcsClient(access_key_id, access_key_secret, region_id)
        
        # 创建请求对象
        request = DescribeDomainRecordsRequest()
        request.set_accept_format('json')
        
        # 设置请求参数
        request.set_DomainName(domain)
        if rr_keyword != '@':
            request.set_RRKeyWord(rr_keyword)
        
        # 发起请求并获取响应
        response = client.do_action_with_exception(request)
        result = json.loads(response.decode('utf-8'))
        
        # 处理响应
        records = result.get('DomainRecords', {}).get('Record', [])
        
        if not records:
            print("未找到匹配的DNS记录")
            return
        
        print(f"\n找到 {len(records)} 条DNS记录:")
        print("-" * 80)
        for record in records:
            # 只输出指定的字段
            print(f"子域名: {record.get('RR')}")
            print(f"记录类型: {record.get('Type')}")
            print(f"记录值: {record.get('Value')}")
            print(f"TTL: {record.get('TTL')}")
            print(f"状态: {record.get('Status')}")
            # 备注字段可能不存在,使用get方法安全获取
            print(f"备注: {record.get('Remark', '无')}")
            print("-" * 80)
            
    except ClientException as e:
        print(f"客户端异常: {e}")
        print(f"错误代码: {e.error_code}")
        print(f"错误消息: {e.message}")
        print(f"请求ID: {e.request_id}")
        
        if "Forbidden" in str(e) or "not authorized" in str(e):
            print("\n权限错误提示:")
            print("1. 请确认权限策略已正确附加到RAM用户")
            print("2. 确认权限策略内容正确: alidns:*, pubdns:*")
            print("3. 权限策略更改后可能需要几分钟生效")
            print("4. 检查是否有其他限制策略")
            print("5. 尝试使用主账户AccessKey测试")
    except ServerException as e:
        print(f"服务器异常: {e}")
        print(f"错误代码: {e.error_code}")
        print(f"错误消息: {e.message}")
        print(f"请求ID: {e.request_id}")
        
        if "Forbidden" in str(e) or "not authorized" in str(e):
            print("\n权限错误提示:")
            print("1. 请确认权限策略已正确附加到RAM用户")
            print("2. 确认权限策略内容正确: alidns:*, pubdns:*")
            print("3. 权限策略更改后可能需要几分钟生效")
            print("4. 检查是否有其他限制策略")
            print("5. 尝试使用主账户AccessKey测试")
    except ValueError as e:
        print(f"域名格式错误: {e}")
    except Exception as e:
        print(f"发生未知错误: {e}")

def get_credentials(cred_file=None):
    """
    获取阿里云凭证:从文件、环境变量或用户输入
    """
    # 1. 如果提供了凭证文件
    if cred_file:
        try:
            with open(cred_file, 'r') as f:
                data = json.load(f)
            access_key_id = data.get('access_key_id')
            access_key_secret = data.get('access_key_secret')
            
            if not access_key_id or not access_key_secret:
                print(f"凭证文件格式错误:缺少access_key_id或access_key_secret字段")
                return None, None
                
            print(f"已从文件 {cred_file} 读取凭证")
            return access_key_id, access_key_secret
        except FileNotFoundError:
            print(f"错误:凭证文件 {cred_file} 不存在")
            return None, None
        except json.JSONDecodeError:
            print(f"错误:凭证文件 {cred_file} 不是有效的JSON格式")
            return None, None
        except Exception as e:
            print(f"读取凭证文件时出错: {e}")
            return None, None
    
    # 2. 尝试从环境变量获取(包括从.env文件加载的变量)
    access_key_id = os.environ.get('ALIYUN_ACCESS_KEY_ID')
    access_key_secret = os.environ.get('ALIYUN_ACCESS_KEY_SECRET')
    
    if access_key_id and access_key_secret:
        print("已从环境变量读取凭证")
        return access_key_id, access_key_secret
    
    # 3. 手动输入凭证
    print("请手动输入阿里云凭证")
    access_key_id = input("请输入阿里云AccessKey ID: ").strip()
    access_key_secret = input("请输入阿里云AccessKey Secret: ").strip()
    
    return access_key_id, access_key_secret

def main():
    # 配置阿里云区域
    REGION_ID = "global"  # 阿里云区域ID
    
    # 设置命令行参数解析
    parser = argparse.ArgumentParser(description='阿里云DNS查询工具')
    parser.add_argument('domain', help='要查询的完整域名 (例如: www.example.com)')
    parser.add_argument('-f', '--file', metavar='FILE', help='从JSON文件读取凭证的路径')
    
    args = parser.parse_args()
    
    # 获取凭证
    access_key_id, access_key_secret = get_credentials(args.file)
    
    if not access_key_id or not access_key_secret:
        print("无法获取有效的凭证,退出程序")
        sys.exit(1)
    
    query_dns_records(access_key_id, access_key_secret, REGION_ID, args.domain)

if __name__ == "__main__":
    main()

三、示例

四、使用场景

  • 日常监控​:定期检查ECS资源使用情况

  • 成本控制​:监控新增实例,避免资源浪费

  • 安全审计​:及时发现未经授权的实例创建

  • 自动化运维​:集成到CI/CD流程中实现自动监控


欢迎您提出问题,并指正代码中的不足
请不要以此视为定论,这只是我的个人经验

相关推荐
Candice_jy几秒前
vscode运行ipynb文件:使用docker中的虚拟环境
服务器·ide·vscode·python·docker·容器·编辑器
流烟默24 分钟前
基于Optuna 贝叶斯优化的自动化XGBoost 超参数调优器
人工智能·python·机器学习·超参数优化
海琴烟Sunshine27 分钟前
leetcode 263. 丑数 python
python·算法·leetcode
AI视觉网奇1 小时前
yolo 获取异常样本 yolo 异常
开发语言·python·yolo
程序员爱钓鱼1 小时前
Python编程实战 面向对象与进阶语法 迭代器与生成器
后端·python·ipython
程序员爱钓鱼1 小时前
Python编程实战 面向对象与进阶语法 JSON数据读写
后端·python·ipython
TH88861 小时前
一体化负氧离子监测站:实时、精准监测空气中负氧离子浓度及其他环境参数
python
苏打水com2 小时前
0基础学前端:100天拿offer实战课(第3天)—— CSS基础美化:给网页“精装修”的5大核心技巧
人工智能·python·tensorflow
wanhengidc2 小时前
云真机和云手机的区别
运维·服务器·游戏·智能手机·云计算
IT小哥哥呀2 小时前
Node.js 实现企业内部消息通知系统(钉钉/企业微信机器人)
node.js·钉钉·企业微信·webhook·后端开发·自动化通知·mysql实战