# Windows系统:
pip3 install aliyun-python-sdk-core-v3
pip3 install aliyun-python-sdk-domain
pip3 install aliyun-python-sdk-alidns
pip3 install requests
pip3 install apscheduler
# CentOS 7 系统:
pip3 install aliyun-python-sdk-core-v3==2.13.10
pip3 install aliyun-python-sdk-domain
pip3 install aliyun-python-sdk-alidns
pip3 install requests
pip3 install apscheduler
# 在系统下先执行 openssl version 查看ssl版本,如是低于1.1.1版本者需要安装指定ssl版本
# 安装指定版本的 urllib3 库,请确保指定的版本与您当前的环境和其他依赖项兼容
pip3 install urllib3==1.25.10
import json
import sys
import os
import requests
import logging
from apscheduler.schedulers.blocking import BlockingScheduler
from aliyunsdkcore.client import AcsClient
from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest
from aliyunsdkalidns.request.v20150109.DeleteSubDomainRecordsRequest import DeleteSubDomainRecordsRequest
class Dnscontroller:
def __init__(self, access_key_id, access_key_secret, region):
"""
初始化 AcsClient
Args:
access_key_id (str): 阿里云访问密钥 ID
access_key_secret (str): 阿里云访问密钥 密钥
region (str): 设置区域, 默认cn-shenzhen
"""
self.client = AcsClient(access_key_id, access_key_secret, region)
# 获取当前脚本文件所在的目录路径
self.current_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
def log(self):
"""日志模块"""
log_filename = os.path.join(self.current_dir, "alyddns.log")
# 配置日志输出格式
log_format = '%(asctime)s - %(levelname)s - %(lineno)d : %(message)s'
logging.basicConfig(level=logging.INFO,
format=log_format,
filename=log_filename,
encoding='utf-8')
logger = logging.getLogger(__name__)
return logger
def add(self, DomainName, RR, Type, Value):
"""
添加新的域名解析记录
Args:
set_DomainName: 传入域名
set_RR: 传入主机记录
set_Type: 传入记录类型
set_Value: 传入记录值
"""
request = AddDomainRecordRequest()
request.set_accept_format('json')
request.set_DomainName(DomainName)
request.set_RR(RR)
request.set_Type(Type)
request.set_Value(Value)
response = self.client.do_action_with_exception(request)
return json.loads(response)
def update(self, RecordId, RR, Type, Value):
"""
修改指定子域名解析记录
Args:
set_RecordId: 传入指定子域名解析的RecordId
set_RR: 传入主机记录
set_Type: 传入记录类型
set_Value: 传入记录值
"""
request = UpdateDomainRecordRequest()
request.set_accept_format('json')
request.set_RecordId(RecordId)
request.set_RR(RR)
request.set_Type(Type)
request.set_Value(Value)
response = self.client.do_action_with_exception(request)
return json.loads(response)
def delete(self, DomainName, RR):
"""
删除指定子域名所有解析记录
Args:
set_DomainName: 传入域名
set_RR: 传入主机记录
"""
request = DeleteSubDomainRecordsRequest()
request.set_accept_format('json')
request.set_DomainName(DomainName)
request.set_RR(RR)
response = self.client.do_action_with_exception(request)
return json.loads(response)
def get_domain_res_record(self, host_record, domain_name):
"""
获取指定子域名解析记录
Args:
set_SubDomain: 传入主机记录.域名, 例如blog.csdn.net
API请求就会针对子域名blog.csdn.net进行操作, 获取该子域名的解析记录
"""
request = DescribeSubDomainRecordsRequest()
request.set_accept_format('json')
request.set_SubDomain(host_record + "." + domain_name)
response = self.client.do_action_with_exception(request)
return json.loads(response)
def domain_name_analysis(self, mode, domain_name, host_record, record_type):
try:
# 获取当前子域名的所有解析列表
domain_list = self.get_domain_res_record(host_record, domain_name)
if mode == "ipv4":
if record_type == "A":
# 获取IPv4,该地址可能会失效,如失效者更换新地址
ipv4 = requests.get('https://ifconfig.me/ip').text
print(f"获取到IPv4地址: {ipv4}")
if domain_list['TotalCount'] == 0:
self.add(domain_name, host_record, record_type, ipv4)
print("新建域名解析成功")
elif domain_list['TotalCount'] == 1:
if domain_list['DomainRecords']['Record'][0]['Value'] != ipv4:
self.update(domain_list["DomainRecords"]["Record"][0]["RecordId"], host_record, record_type, ipv4)
print("修改域名解析成功—update")
else:
print("IPv4地址没变")
else:
self.delete(domain_name, host_record)
self.add(domain_name, host_record, record_type, ipv4)
print("修改域名解析成功—delete")
else:
self.log().error("record_type记录类型(ipv4)填写不正确, 必须是: A")
sys.exit()
elif mode == "ipv6":
if record_type == "AAAA":
# 获取IPv6,该地址可能会失效,如失效者更换新地址
ipv6 = requests.get("https://6.ipw.cn/api/ip/myip?json").text
get_ipv6 = json.loads(ipv6)["IP"]
print(f"获取到IPv6地址: {get_ipv6}")
if domain_list['TotalCount'] == 0:
self.add(domain_name, host_record, record_type, get_ipv6)
print("新建IPV6域名解析成功")
elif domain_list['TotalCount'] == 1:
if domain_list['DomainRecords']['Record'][0]['Value'] != get_ipv6:
self.update(domain_list["DomainRecords"]["Record"][0]["RecordId"], host_record, record_type, get_ipv6)
print("修改IPV6域名解析成功—update")
else:
print("IPV6地址没变")
else:
self.delete(domain_name, host_record)
self.add(domain_name, host_record, record_type, get_ipv6)
print("修改IPV6域名解析成功—delete")
else:
self.log().error("record_type记录类型(ipv6)填写不正确, 必须是: AAAA")
sys.exit()
else:
self.log().error("mode类型填写不正确, 必须是: ipv4 & ipv6")
sys.exit()
except Exception as i:
self.log().error(i)
sys.exit()
if __name__ == "__main__":
def execute():
run = Dnscontroller("阿里云账号密钥 ID", "阿里云账号密钥 密钥", "cn-shenzhen")
run.domain_name_analysis("类型(ipv4 & ipv6)", "域名", "主机记录", "记录类型(A & AAAA)")
# 先执行一次任务
execute()
# BlockingScheduler调度器,适用于小型应用程序或简单任务调度的场景
scheduler = BlockingScheduler(timezone='Asia/Shanghai')
# 按间隔一定时间执行任务:seconds=秒;minutes=分钟;hours=小时
scheduler.add_job(execute, 'interval', minutes=10)
scheduler.start()
1.把alyddns.py文件上传到服务器“/home”目录下,并赋予权限
cd /home
chmod +x alyddns.py
2.脚本添加到systemd服务管理器中
# ①创建一个新的服务单元文件
sudo vi /etc/systemd/system/alyddns.service
# ②在该文件中,插入以下内容:
[Unit]
Description=aly DDNS
After=network.target network-online.target systemd-networkd-wait-online.service
[Service]
ExecStart=/usr/bin/python3 /home/alyddns.py
WorkingDirectory=/home/
[Install]
WantedBy=multi-user.target
# Description:描述该服务的文本,可以随意命名,用于标识该服务的目的
# After:定义所依赖的其他系统单元(units)实例中表示:
# network.target表示基本的网络服务已启动完成
# network-online.target表示网络连接已准备就绪
# systemd-networkd-wait-online.service确保网络连接建立后继续启动
# ExecStart: 指定要执行的命令或脚本(/usr/bin/python3程序路径,根据实际情况替换。/home/alyddns.py脚本路径)
# WorkingDirectory: 指定服务的工作目录
# WantedBy: 指定服务所属的运行级别。在CentOS 7中,multi-user.target表示该服务将在多用户模式下启动
# ③保存并关闭文件,重新加载systemd配置
sudo systemctl daemon-reload
# ④启用服务以在开机时自动运行
sudo systemctl enable alyddns.service
# ⑤启动服务,使其立即生效
sudo systemctl start alyddns.service
# 停止服务
sudo systemctl stop alyddns.service
# 查看服务状态
sudo systemctl status alyddns.service