258 lines
7.9 KiB
Bash
Executable File
258 lines
7.9 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# DNS 同步脚本
|
||
# 比较 FTP 根目录的 dns.conf 和本地的 dns.conf,如果有变化则同步到 /etc/resolv.conf
|
||
|
||
set -e
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 日志函数 - 输出到 stderr 避免影响函数返回值
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1" >&2
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1" >&2
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}[WARNING]${NC} $1" >&2
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1" >&2
|
||
}
|
||
|
||
# 获取脚本所在目录
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
LOCAL_DNS_CONF="/opt/argus-metric/dns.conf"
|
||
REMOTE_DNS_CONF_URL=""
|
||
RESOLV_CONF="/etc/resolv.conf"
|
||
LOG_FILE="/opt/argus-metric/.dns_sync.log"
|
||
|
||
# 从环境变量或配置文件获取 FTP 服务器信息
|
||
get_ftp_config() {
|
||
# 优先从环境变量获取配置
|
||
log_info "获取 FTP 配置信息..."
|
||
|
||
# 如果环境变量中没有设置,则尝试从配置文件读取
|
||
if [[ -z "$FTP_SERVER" || -z "$FTP_USER" || -z "$FTP_PASSWORD" ]]; then
|
||
local config_file="$SCRIPT_DIR/config.env"
|
||
if [[ -f "$config_file" ]]; then
|
||
log_info "从配置文件读取 FTP 配置: $config_file"
|
||
source "$config_file"
|
||
fi
|
||
else
|
||
log_info "使用环境变量中的 FTP 配置"
|
||
fi
|
||
|
||
# 设置默认值(如果环境变量和配置文件都没有设置)
|
||
FTP_SERVER="${FTP_SERVER:-localhost}"
|
||
FTP_USER="${FTP_USER:-ftpuser}"
|
||
FTP_PASSWORD="${FTP_PASSWORD:-ZGClab1234!}"
|
||
|
||
# 构建远程 DNS 配置文件 URL
|
||
REMOTE_DNS_CONF_URL="ftp://${FTP_USER}:${FTP_PASSWORD}@${FTP_SERVER}/dns.conf"
|
||
|
||
log_info "FTP 配置来源: ${FTP_CONFIG_SOURCE:-环境变量/配置文件}"
|
||
}
|
||
|
||
# 下载远程 DNS 配置文件
|
||
download_remote_dns_conf() {
|
||
local temp_file="/tmp/dns.conf.remote.$$"
|
||
|
||
log_info "从 FTP 服务器下载 DNS 配置文件..."
|
||
log_info "远程地址: $REMOTE_DNS_CONF_URL"
|
||
log_info "FTP 服务器: $FTP_SERVER"
|
||
log_info "FTP 用户: $FTP_USER"
|
||
|
||
# 先测试 FTP 连接
|
||
log_info "测试 FTP 连接..."
|
||
if curl -u "${FTP_USER}:${FTP_PASSWORD}" -sfI "ftp://${FTP_SERVER}/" >/dev/null 2>&1; then
|
||
log_success "FTP 服务器连接成功"
|
||
else
|
||
log_error "无法连接到 FTP 服务器: $FTP_SERVER"
|
||
log_error "请检查:"
|
||
log_error " 1. FTP 服务器是否运行"
|
||
log_error " 2. 网络连接是否正常"
|
||
log_error " 3. 服务器地址是否正确"
|
||
return 1
|
||
fi
|
||
|
||
# 测试 dns.conf 文件是否存在
|
||
log_info "检查远程 dns.conf 文件是否存在..."
|
||
if curl -u "${FTP_USER}:${FTP_PASSWORD}" -sfI "ftp://${FTP_SERVER}/dns.conf" >/dev/null 2>&1; then
|
||
log_success "远程 dns.conf 文件存在"
|
||
else
|
||
log_error "远程 dns.conf 文件不存在或无法访问"
|
||
log_error "请检查 FTP 服务器根目录下是否有 dns.conf 文件"
|
||
return 1
|
||
fi
|
||
|
||
# 尝试下载文件
|
||
log_info "开始下载 dns.conf 文件..."
|
||
if curl -u "${FTP_USER}:${FTP_PASSWORD}" -sf "ftp://${FTP_SERVER}/dns.conf" -o "$temp_file" 2>/dev/null; then
|
||
log_success "远程 DNS 配置文件下载成功"
|
||
echo "$temp_file"
|
||
else
|
||
log_error "下载 dns.conf 文件失败"
|
||
log_error "尝试手动测试命令:"
|
||
log_error " curl -u ${FTP_USER}:${FTP_PASSWORD} ftp://${FTP_SERVER}/dns.conf"
|
||
rm -f "$temp_file"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 比较两个文件是否相同
|
||
compare_files() {
|
||
local file1="$1"
|
||
local file2="$2"
|
||
|
||
if [[ ! -f "$file1" || ! -f "$file2" ]]; then
|
||
return 1
|
||
fi
|
||
|
||
# 使用 diff 比较文件内容
|
||
if diff -q "$file1" "$file2" >/dev/null 2>&1; then
|
||
return 0 # 文件相同
|
||
else
|
||
return 1 # 文件不同
|
||
fi
|
||
}
|
||
|
||
# 将 DNS 配置添加到 /etc/resolv.conf 开头
|
||
update_resolv_conf() {
|
||
local dns_conf_file="$1"
|
||
|
||
log_info "更新 /etc/resolv.conf 文件..."
|
||
|
||
# 创建临时文件
|
||
local temp_resolv="/tmp/resolv.conf.$$"
|
||
|
||
# 将 dns.conf 内容转换为 nameserver 添加到临时文件开头
|
||
while IFS= read -r line; do
|
||
# 跳过空行和注释
|
||
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
||
# 验证 IP 格式
|
||
if [[ "$line" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then
|
||
echo "nameserver $line" >> "$temp_resolv"
|
||
log_info "添加 DNS 到临时文件: $line"
|
||
else
|
||
log_warning "跳过无效 DNS: $line"
|
||
fi
|
||
done < "$dns_conf_file"
|
||
|
||
# 将原 resolv.conf 内容追加到临时文件后面
|
||
if [[ -f "$RESOLV_CONF" ]]; then
|
||
cat "$RESOLV_CONF" >> "$temp_resolv"
|
||
fi
|
||
|
||
# 判断是否是 root
|
||
if [[ $(id -u) -eq 0 ]]; then
|
||
# root 直接写入
|
||
tee "$RESOLV_CONF" < "$temp_resolv" >/dev/null
|
||
chmod 644 "$RESOLV_CONF"
|
||
else
|
||
# 非 root 尝试使用 sudo
|
||
if command -v sudo >/dev/null 2>&1; then
|
||
sudo tee "$RESOLV_CONF" < "$temp_resolv" >/dev/null
|
||
sudo chmod 644 "$RESOLV_CONF"
|
||
else
|
||
log_error "非 root 用户且系统未安装 sudo,无法更新 /etc/resolv.conf"
|
||
rm -f "$temp_resolv"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# 清理临时文件
|
||
rm -f "$temp_resolv"
|
||
|
||
log_success "/etc/resolv.conf 已更新"
|
||
}
|
||
|
||
# 记录同步日志
|
||
log_sync() {
|
||
local message="$1"
|
||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||
echo "[$timestamp] $message" >> "$LOG_FILE"
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
log_info "开始 DNS 同步检查..."
|
||
log_sync "DNS 同步检查开始"
|
||
|
||
# 确保系统目录存在
|
||
mkdir -p "/opt/argus-metric"
|
||
|
||
# 获取 FTP 配置
|
||
get_ftp_config
|
||
|
||
# 检查本地 DNS 配置文件是否存在
|
||
if [[ ! -f "$LOCAL_DNS_CONF" ]]; then
|
||
log_warning "本地 DNS 配置文件不存在: $LOCAL_DNS_CONF"
|
||
log_warning "将下载远程配置文件并更新系统 DNS 设置"
|
||
|
||
# 下载远程配置文件
|
||
if remote_file=$(download_remote_dns_conf); then
|
||
# 复制到本地
|
||
cp "$remote_file" "$LOCAL_DNS_CONF"
|
||
log_success "远程 DNS 配置文件已保存到本地"
|
||
|
||
# 更新 resolv.conf
|
||
update_resolv_conf "$LOCAL_DNS_CONF"
|
||
log_sync "首次同步完成,DNS 配置已更新"
|
||
|
||
# 清理临时文件
|
||
rm -f "$remote_file"
|
||
else
|
||
log_error "无法下载远程 DNS 配置文件,同步失败"
|
||
log_sync "同步失败:无法下载远程配置文件"
|
||
exit 1
|
||
fi
|
||
else
|
||
log_info "本地 DNS 配置文件存在: $LOCAL_DNS_CONF"
|
||
|
||
# 下载远程配置文件进行比较
|
||
if remote_file=$(download_remote_dns_conf); then
|
||
# 比较文件
|
||
if compare_files "$LOCAL_DNS_CONF" "$remote_file"; then
|
||
log_info "DNS 配置文件无变化,无需更新"
|
||
log_sync "DNS 配置文件无变化"
|
||
else
|
||
log_info "检测到 DNS 配置文件有变化,开始同步..."
|
||
log_sync "检测到 DNS 配置文件变化,开始同步"
|
||
|
||
# 更新本地配置文件
|
||
cp "$remote_file" "$LOCAL_DNS_CONF"
|
||
log_success "本地 DNS 配置文件已更新"
|
||
|
||
# 更新 resolv.conf
|
||
update_resolv_conf "$LOCAL_DNS_CONF"
|
||
log_sync "DNS 配置同步完成"
|
||
fi
|
||
|
||
# 清理临时文件
|
||
rm -f "$remote_file"
|
||
else
|
||
log_error "无法下载远程 DNS 配置文件,跳过本次同步"
|
||
log_sync "同步失败:无法下载远程配置文件"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
log_success "DNS 同步检查完成"
|
||
log_sync "DNS 同步检查完成"
|
||
}
|
||
|
||
# 脚本入口
|
||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||
main "$@"
|
||
fi
|