fix vps_init

This commit is contained in:
eddy
2026-06-18 02:35:53 +08:00
parent a7e396beee
commit fe6f98a1fc
+131 -55
View File
@@ -225,6 +225,59 @@ handle_error() {
# 设置错误跟踪 # 设置错误跟踪
trap 'handle_error $LINENO' ERR trap 'handle_error $LINENO' ERR
# ===========================================
# 安全更新软件源:自动检测并禁用失效的软件源
# (例如 Debian 版本归档后失效的 *-backports 源)后重试
# ===========================================
apt_update_safe() {
local tmp retry=0
tmp=$(mktemp)
while :; do
# 执行更新,忽略退出码(失效的源会让 apt 返回非0)
apt-get update > "$tmp" 2>&1 || true
cat "$tmp" >> "$LOG_FILE"
cat "$tmp"
# 没有检测到失效源,更新成功
if ! grep -qiE "no longer has a Release file|404 +Not Found|Failed to fetch" "$tmp"; then
rm -f "$tmp"
return 0
fi
# 已尝试修复过一次,仍有问题则忽略并继续,避免死循环
if [ "$retry" -ge 1 ]; then
log "${YELLOW}部分软件源仍不可用,将忽略失效源并继续${NC}"
rm -f "$tmp"
return 0
fi
log "${YELLOW}检测到失效的软件源,正在自动禁用...${NC}"
# 从 apt 输出中提取失效的套件名(位于 "<url> <suite> Release" 中)
local suites suite
suites=$(grep -oE "The repository '[^']+ Release'" "$tmp" \
| sed -E "s/The repository '(.*) Release'/\1/" \
| awk '{print $NF}' | sort -u)
if [ -z "$suites" ]; then
log "${YELLOW}无法解析失效套件名,将忽略失效源并继续${NC}"
rm -f "$tmp"
return 0
fi
for suite in $suites; do
[ -n "$suite" ] || continue
log "${YELLOW} - 禁用失效套件: ${suite}${NC}"
for f in /etc/apt/sources.list $(ls /etc/apt/sources.list.d/*.list 2>/dev/null); do
[ -f "$f" ] || continue
# 注释掉引用该失效套件的未注释行
sed -i -E "s|^([^#].*[[:space:]]${suite}[[:space:]].*)$|#\1|g" "$f"
done
done
retry=$((retry + 1))
done
}
# =========================================== # ===========================================
# 1. 系统更新 # 1. 系统更新
# =========================================== # ===========================================
@@ -238,7 +291,7 @@ fi
# 更新系统包 # 更新系统包
if [ "$OS_TYPE" = "debian" ]; then if [ "$OS_TYPE" = "debian" ]; then
apt update -y || log "${RED}更新软件源失败${NC}" apt_update_safe
DEBIAN_FRONTEND=noninteractive apt full-upgrade -y || log "${RED}系统升级失败${NC}" DEBIAN_FRONTEND=noninteractive apt full-upgrade -y || log "${RED}系统升级失败${NC}"
apt install -y wget curl sudo vim git ufw net-tools htop iftop || log "${RED}安装基础软件包失败${NC}" apt install -y wget curl sudo vim git ufw net-tools htop iftop || log "${RED}安装基础软件包失败${NC}"
log "${GREEN}系统更新完成,安装了常用工具${NC}" log "${GREEN}系统更新完成,安装了常用工具${NC}"
@@ -378,22 +431,32 @@ if command -v docker &> /dev/null; then
else else
# 安装Docker # 安装Docker
if [ "$OS_TYPE" = "debian" ]; then if [ "$OS_TYPE" = "debian" ]; then
# 先确保软件源可用(官方脚本内部也会执行 apt update)
apt_update_safe
# 使用官方安装脚本 # 使用官方安装脚本
curl -fsSL https://get.docker.com -o get-docker.sh curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh sh get-docker.sh || log "${RED}Docker安装脚本执行出现问题${NC}"
rm get-docker.sh rm -f get-docker.sh
systemctl enable docker
# 安装Docker Compose # 校验Docker是否真正安装成功
if ! command -v docker-compose &> /dev/null; then if command -v docker &> /dev/null; then
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose systemctl enable docker 2>/dev/null || log "${YELLOW}无法设置Docker开机自启${NC}"
chmod +x /usr/local/bin/docker-compose systemctl start docker 2>/dev/null || true
log "${GREEN}Docker Compose 安装完成${NC}"
# 安装Docker Compose
if ! command -v docker-compose &> /dev/null; then
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
log "${GREEN}Docker Compose 安装完成${NC}"
fi
log "${GREEN}Docker安装完成,版本信息:${NC}"
docker --version
docker-compose --version 2>/dev/null || docker compose version 2>/dev/null || true
else
log "${RED}Docker安装失败,请检查网络或软件源后重试,可手动执行: curl -fsSL https://get.docker.com | sh${NC}"
fi fi
log "${GREEN}Docker安装完成,版本信息:${NC}"
docker --version
docker-compose --version
else else
log "${YELLOW}非Debian系统,请手动安装Docker${NC}" log "${YELLOW}非Debian系统,请手动安装Docker${NC}"
fi fi
@@ -406,7 +469,8 @@ log "${BLUE}[6/10] 防火墙设置开始...${NC}"
# 安装UFW # 安装UFW
if [ "$OS_TYPE" = "debian" ]; then if [ "$OS_TYPE" = "debian" ]; then
apt update -y && apt install -y ufw net-tools lsof apt_update_safe
apt install -y ufw net-tools lsof || log "${RED}安装防火墙相关软件包(ufw/net-tools/lsof)失败${NC}"
# 确保防火墙默认策略 # 确保防火墙默认策略
ufw default deny incoming ufw default deny incoming
@@ -441,8 +505,8 @@ if [ "$OS_TYPE" = "debian" ]; then
LISTENING_PORTS=$(netstat -tlnp 2>/dev/null | grep "LISTEN" | awk '{print $4}' | awk -F: '{print $NF}' | sort -n | uniq) LISTENING_PORTS=$(netstat -tlnp 2>/dev/null | grep "LISTEN" | awk '{print $4}' | awk -F: '{print $NF}' | sort -n | uniq)
# 使用lsof作为备选方法 # 使用lsof作为备选方法
if [ -z "$LISTENING_PORTS" ]; then if [ -z "$LISTENING_PORTS" ] && command -v lsof &> /dev/null; then
LISTENING_PORTS=$(lsof -i -P -n | grep LISTEN | awk '{print $9}' | awk -F: '{print $NF}' | sort -n | uniq) LISTENING_PORTS=$(lsof -i -P -n 2>/dev/null | grep LISTEN | awk '{print $9}' | awk -F: '{print $NF}' | sort -n | uniq)
fi fi
# 如果仍然为空,提示手动检查 # 如果仍然为空,提示手动检查
@@ -457,7 +521,10 @@ if [ "$OS_TYPE" = "debian" ]; then
"$PORT" -lt "65535" && "$PORT" -gt "1024" ]]; then "$PORT" -lt "65535" && "$PORT" -gt "1024" ]]; then
# 尝试找出服务名称 # 尝试找出服务名称
SERVICE=$(lsof -i:$PORT -sTCP:LISTEN | grep -v "COMMAND" | awk '{print $1}' | head -1) SERVICE=""
if command -v lsof &> /dev/null; then
SERVICE=$(lsof -i:$PORT -sTCP:LISTEN 2>/dev/null | grep -v "COMMAND" | awk '{print $1}' | head -1)
fi
if [ -z "$SERVICE" ]; then if [ -z "$SERVICE" ]; then
SERVICE=$(netstat -tlnp 2>/dev/null | grep ":$PORT" | awk '{print $7}' | cut -d"/" -f2 | head -1) SERVICE=$(netstat -tlnp 2>/dev/null | grep ":$PORT" | awk '{print $7}' | cut -d"/" -f2 | head -1)
fi fi
@@ -579,18 +646,26 @@ log "${BLUE}[9/10] Fail2ban安装开始...${NC}"
if [ "$OS_TYPE" = "debian" ]; then if [ "$OS_TYPE" = "debian" ]; then
# 安装Fail2ban # 安装Fail2ban
apt update -y && apt install -y fail2ban apt_update_safe
systemctl start fail2ban apt install -y fail2ban || log "${RED}安装Fail2ban失败${NC}"
systemctl enable fail2ban
# 配置Fail2ban # 校验是否真正安装成功
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local if ! command -v fail2ban-client &> /dev/null && ! dpkg -l fail2ban 2>/dev/null | grep -q "^ii"; then
log "${RED}Fail2ban未成功安装,跳过其配置(请检查软件源后重试)${NC}"
else
systemctl enable fail2ban 2>/dev/null || log "${YELLOW}无法设置Fail2ban开机自启${NC}"
# 清理任何现有配置 # 配置Fail2ban
rm -rf /etc/fail2ban/jail.d/* 2>/dev/null || true mkdir -p /etc/fail2ban/jail.d
if [ -f /etc/fail2ban/jail.conf ]; then
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
fi
# 创建SSH防护配置 # 清理任何现有配置
cat <<EOF > /etc/fail2ban/jail.d/sshd.local rm -rf /etc/fail2ban/jail.d/* 2>/dev/null || true
# 创建SSH防护配置
cat <<EOF > /etc/fail2ban/jail.d/sshd.local
[sshd] [sshd]
enabled = true enabled = true
mode = normal mode = normal
@@ -602,44 +677,45 @@ bantime = 1h
findtime = 10m findtime = 10m
EOF EOF
# 重启Fail2ban # 重启Fail2ban
log "${YELLOW}重启Fail2ban服务...${NC}" log "${YELLOW}重启Fail2ban服务...${NC}"
systemctl restart fail2ban systemctl restart fail2ban 2>/dev/null || systemctl start fail2ban 2>/dev/null || log "${RED}Fail2ban服务启动失败${NC}"
# 等待服务启动完成 # 等待服务启动完成
log "${YELLOW}等待Fail2ban服务完全启动...${NC}" log "${YELLOW}等待Fail2ban服务完全启动...${NC}"
sleep 5 sleep 5
# 检查服务状态 # 检查服务状态
if systemctl is-active --quiet fail2ban; then if systemctl is-active --quiet fail2ban; then
log "${GREEN}Fail2ban服务已成功启动${NC}" log "${GREEN}Fail2ban服务已成功启动${NC}"
# 显示Fail2ban状态(使用错误处理避免脚本终止) # 显示Fail2ban状态(使用错误处理避免脚本终止)
log "${YELLOW}获取Fail2ban状态信息...${NC}" log "${YELLOW}获取Fail2ban状态信息...${NC}"
# 尝试获取fail2ban状态,忽略可能的错误 # 尝试获取fail2ban状态,忽略可能的错误
fail2ban-client status >/dev/null 2>&1 || log "${YELLOW}无法获取fail2ban综合状态,但这不影响功能${NC}" fail2ban-client status >/dev/null 2>&1 || log "${YELLOW}无法获取fail2ban综合状态,但这不影响功能${NC}"
# 尝试获取sshd监狱状态 # 尝试获取sshd监狱状态
if fail2ban-client status sshd >/dev/null 2>&1; then if fail2ban-client status sshd >/dev/null 2>&1; then
log "${GREEN}SSH防护已成功配置${NC}" log "${GREEN}SSH防护已成功配置${NC}"
# 只有在前面成功的情况下才显示详细信息 # 只有在前面成功的情况下才显示详细信息
fail2ban-client status sshd fail2ban-client status sshd
else
log "${YELLOW}无法获取SSH监狱状态,这可能是因为服务刚刚启动或配置需要更多时间生效${NC}"
log "${YELLOW}如果在重启后仍有问题,请检查 /var/log/fail2ban.log${NC}"
fi
# 显示服务状态
systemctl status fail2ban --no-pager || true
else else
log "${YELLOW}无法获取SSH监狱状态,这可能是因为服务刚刚启动或配置需要更多时间生效${NC}" log "${RED}Fail2ban服务启动失败,请检查错误日志${NC}"
log "${YELLOW}如果在重启后仍有问题,请检查 /var/log/fail2ban.log${NC}" log "${YELLOW}尝试查看Fail2ban日志获取错误详情:${NC}"
tail -n 20 /var/log/fail2ban.log 2>/dev/null || log "${RED}无法读取Fail2ban日志${NC}"
fi fi
# 显示服务状态 log "${GREEN}Fail2ban安装和配置完成${NC}"
systemctl status fail2ban --no-pager || true log "${YELLOW}如果出现临时错误,服务器重启后通常会正常工作${NC}"
else
log "${RED}Fail2ban服务启动失败,请检查错误日志${NC}"
log "${YELLOW}尝试查看Fail2ban日志获取错误详情:${NC}"
tail -n 20 /var/log/fail2ban.log 2>/dev/null || log "${RED}无法读取Fail2ban日志${NC}"
fi fi
log "${GREEN}Fail2ban安装和配置完成${NC}"
log "${YELLOW}如果出现临时错误,服务器重启后通常会正常工作${NC}"
else else
log "${YELLOW}非Debian系统,请手动安装Fail2ban${NC}" log "${YELLOW}非Debian系统,请手动安装Fail2ban${NC}"
fi fi