fix vps_init
This commit is contained in:
+142
-66
@@ -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是否真正安装成功
|
||||||
# 安装Docker Compose
|
if command -v docker &> /dev/null; then
|
||||||
if ! command -v docker-compose &> /dev/null; then
|
systemctl enable docker 2>/dev/null || log "${YELLOW}无法设置Docker开机自启${NC}"
|
||||||
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
systemctl start docker 2>/dev/null || true
|
||||||
chmod +x /usr/local/bin/docker-compose
|
|
||||||
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
|
if ! command -v fail2ban-client &> /dev/null && ! dpkg -l fail2ban 2>/dev/null | grep -q "^ii"; then
|
||||||
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
|
log "${RED}Fail2ban未成功安装,跳过其配置(请检查软件源后重试)${NC}"
|
||||||
|
else
|
||||||
# 清理任何现有配置
|
systemctl enable fail2ban 2>/dev/null || log "${YELLOW}无法设置Fail2ban开机自启${NC}"
|
||||||
rm -rf /etc/fail2ban/jail.d/* 2>/dev/null || true
|
|
||||||
|
# 配置Fail2ban
|
||||||
# 创建SSH防护配置
|
mkdir -p /etc/fail2ban/jail.d
|
||||||
cat <<EOF > /etc/fail2ban/jail.d/sshd.local
|
if [ -f /etc/fail2ban/jail.conf ]; then
|
||||||
|
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 清理任何现有配置
|
||||||
|
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
|
||||||
@@ -601,45 +676,46 @@ maxretry = 5
|
|||||||
bantime = 1h
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user