Co-authored-by: sundapeng.sdp <sundapeng@hashdata.cn> Reviewed-on: #27 Reviewed-by: yuyr <yuyr@zgclab.edu.cn> Reviewed-by: xuxt <xuxt@zgclab.edu.cn>
144 lines
4.6 KiB
Bash
Executable File
144 lines
4.6 KiB
Bash
Executable File
#!/bin/bash
|
||
set -e
|
||
|
||
# 颜色
|
||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||
|
||
# 日志函数
|
||
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"
|
||
RESOLV_CONF="/etc/resolv.conf"
|
||
ALT_RESOLV_CONF="/run/resolv.conf"
|
||
LOG_FILE="/opt/argus-metric/.dns_sync.log"
|
||
REMOTE_DNS_CONF_URL=""
|
||
|
||
# 获取 FTP 配置
|
||
get_ftp_config() {
|
||
log_info "获取 FTP 配置信息..."
|
||
if [[ -z "$FTP_SERVER" || -z "$FTP_USER" || -z "$FTP_PASSWORD" ]]; then
|
||
[[ -f "$SCRIPT_DIR/config.env" ]] && source "$SCRIPT_DIR/config.env"
|
||
fi
|
||
FTP_SERVER="${FTP_SERVER:-localhost}"
|
||
FTP_USER="${FTP_USER:-ftpuser}"
|
||
FTP_PASSWORD="${FTP_PASSWORD:-ZGClab1234!}"
|
||
REMOTE_DNS_CONF_URL="ftp://${FTP_USER}:${FTP_PASSWORD}@${FTP_SERVER}/dns.conf"
|
||
}
|
||
|
||
# 下载远程 dns.conf
|
||
download_remote_dns_conf() {
|
||
local tmp="/tmp/dns.remote.$$"
|
||
log_info "测试 FTP 连接..."
|
||
if ! curl -u "${FTP_USER}:${FTP_PASSWORD}" -sfI "ftp://${FTP_SERVER}/" >/dev/null; then
|
||
log_error "无法连接到 FTP 服务器: $FTP_SERVER"; return 1
|
||
fi
|
||
if ! curl -u "${FTP_USER}:${FTP_PASSWORD}" -sf "ftp://${FTP_SERVER}/dns.conf" -o "$tmp" 2>/dev/null; then
|
||
log_error "下载 dns.conf 失败"; rm -f "$tmp"; return 1
|
||
fi
|
||
echo "$tmp"
|
||
}
|
||
|
||
# 文件比较
|
||
compare_files() { diff -q "$1" "$2" >/dev/null 2>&1; }
|
||
|
||
# 从 dns.conf 提取有效 IP
|
||
get_dns_ips() {
|
||
grep -Eo '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' "$1" | sort -u
|
||
}
|
||
|
||
# 安全更新 resolv.conf(保留符号链接)
|
||
update_resolv_conf() {
|
||
local dns_conf="$1"
|
||
local dns_ips
|
||
mapfile -t dns_ips < <(get_dns_ips "$dns_conf")
|
||
[[ ${#dns_ips[@]} -eq 0 ]] && { log_warning "未检测到有效 DNS"; return; }
|
||
|
||
local target_file="$RESOLV_CONF"
|
||
if [[ ! -w "$RESOLV_CONF" ]]; then
|
||
log_warning "/etc/resolv.conf 不可写,使用兜底路径 $ALT_RESOLV_CONF"
|
||
target_file="$ALT_RESOLV_CONF"
|
||
fi
|
||
|
||
local temp="/tmp/resolv.new.$$"
|
||
cp "$target_file" "${target_file}.backup.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true
|
||
log_info "更新 DNS 配置文件: $target_file"
|
||
|
||
# 写入新的 nameserver 行
|
||
for ip in "${dns_ips[@]}"; do
|
||
echo "nameserver $ip"
|
||
done >"$temp"
|
||
|
||
# 追加原内容(去掉重复 nameserver)
|
||
grep -v '^nameserver' "$target_file" >>"$temp" 2>/dev/null || true
|
||
awk '!a[$0]++' "$temp" >"${temp}.uniq"
|
||
|
||
# ⚙️ 使用 cat 原地覆盖,避免 mv 引发 “设备忙”
|
||
if cat "${temp}.uniq" >"$target_file" 2>/dev/null; then
|
||
chmod 644 "$target_file"
|
||
log_success "DNS 更新完成: ${dns_ips[*]}"
|
||
else
|
||
log_error "无法写入 $target_file,可能被系统锁定"
|
||
fi
|
||
|
||
rm -f "$temp" "${temp}.uniq"
|
||
}
|
||
|
||
# 检查 resolv.conf 是否包含 dns.conf 内容
|
||
ensure_dns_in_resolv() {
|
||
local dns_conf="$1"
|
||
local dns_ips
|
||
mapfile -t dns_ips < <(get_dns_ips "$dns_conf")
|
||
[[ ${#dns_ips[@]} -eq 0 ]] && return
|
||
|
||
for ip in "${dns_ips[@]}"; do
|
||
if ! grep -q "nameserver $ip" "$RESOLV_CONF" 2>/dev/null; then
|
||
log_warning "检测到 /etc/resolv.conf 缺少 $ip,执行兜底修复"
|
||
update_resolv_conf "$dns_conf"
|
||
return
|
||
fi
|
||
done
|
||
log_info "/etc/resolv.conf 已包含所有 DNS"
|
||
}
|
||
|
||
log_sync() { echo "[$(date '+%F %T')] $1" >>"$LOG_FILE"; }
|
||
|
||
main() {
|
||
log_info "开始 DNS 同步检查..."
|
||
mkdir -p /opt/argus-metric
|
||
|
||
get_ftp_config
|
||
local remote_file
|
||
if ! remote_file=$(download_remote_dns_conf); then
|
||
log_error "下载失败"; log_sync "同步失败"; exit 1
|
||
fi
|
||
|
||
if [[ ! -f "$LOCAL_DNS_CONF" ]]; then
|
||
log_info "本地 dns.conf 不存在,初始化..."
|
||
cp "$remote_file" "$LOCAL_DNS_CONF"
|
||
update_resolv_conf "$LOCAL_DNS_CONF"
|
||
log_sync "首次同步完成"
|
||
else
|
||
if compare_files "$LOCAL_DNS_CONF" "$remote_file"; then
|
||
log_info "dns.conf 无变化"
|
||
ensure_dns_in_resolv "$LOCAL_DNS_CONF"
|
||
log_sync "dns.conf 无变化,执行兜底检查"
|
||
else
|
||
log_info "检测到 DNS 配置更新"
|
||
cp "$remote_file" "$LOCAL_DNS_CONF"
|
||
update_resolv_conf "$LOCAL_DNS_CONF"
|
||
log_sync "DNS 配置同步完成"
|
||
fi
|
||
fi
|
||
|
||
rm -f "$remote_file"
|
||
log_success "DNS 同步流程完成"
|
||
}
|
||
|
||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||
main "$@"
|
||
fi
|