shell
#!/bin/bash
# 安全版救援修复脚本 - 融合启动优化功能
echo "=== 开始创建救援修复脚本(融合启动优化功能) ==="
# 创建脚本文件
cat > /tmp/rescue_fix_with_optimization.sh << 'SCRIPT_EOF'
#!/bin/bash
# rescue-fix-ubuntu.sh - 安全执行版(融合启动优化)
# 在救援系统(CentOS 8 Stream)中自动修复Ubuntu启动问题并优化启动速度
set -e # 遇到错误立即退出
LOG_FILE="/tmp/rescue_fix_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "=== Ubuntu 22.04 内核启动修复与优化脚本 ==="
echo "开始时间: $(date)"
echo "日志文件: $LOG_FILE"
echo "============================================"
# 定义颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; }
# 步骤1:检查是否已挂载
info "步骤1:检查挂载点..."
if ! mountpoint -q /mnt; then
info "正在挂载 /dev/vdb1 到 /mnt..."
mount /dev/vdb1 /mnt || {
error "挂载失败!请手动执行: mount /dev/vdb1 /mnt"
exit 1
}
else
info "/mnt 已挂载"
fi
# 步骤2:备份原GRUB配置
info "步骤2:备份GRUB配置..."
if [ -f /mnt/etc/default/grub ]; then
cp /mnt/etc/default/grub /mnt/etc/default/grub.backup.$(date +%Y%m%d_%H%M%S)
fi
# 步骤3:修改GRUB配置
info "步骤3:修改GRUB配置..."
cat > /mnt/etc/default/grub << 'GRUB_EOF'
# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
GRUB_DEFAULT="1>3"
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""
GRUB_EOF
info "✅ GRUB配置已更新"
# 步骤4:挂载系统目录并chroot
info "步骤4:准备chroot环境..."
cd /mnt || { error "无法进入 /mnt"; exit 1; }
# 挂载必要的目录
for dir in dev proc sys run; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
fi
mount --bind "/$dir" "$dir" && info "✅ 挂载 /$dir"
done
# 复制DNS配置 - 修复文件不存在的问题
info "复制DNS配置..."
if [ -f /etc/resolv.conf ]; then
cat /etc/resolv.conf > etc/resolv.conf 2>/dev/null && info "✅ 复制DNS配置" || warn "复制DNS配置失败(可忽略)"
else
warn "/etc/resolv.conf 不存在,跳过DNS配置"
# 创建一个空的resolv.conf以避免后续错误
touch etc/resolv.conf 2>/dev/null || true
fi
# 步骤5:chroot执行修复
info "步骤5:在chroot中执行修复..."
# 执行chroot命令
chroot /mnt /bin/bash << 'CHROOT_EOF'
#!/bin/bash
set -e
echo "=== 开始在chroot环境中修复 ==="
# ===== 在这里设置您想要的内核版本号 =====
# 直接修改下面的数字即可,例如改为164或156
TARGET_VERSION="168"
# ========================================
echo "目标内核版本: 5.15.0-${TARGET_VERSION}-generic"
# 检查并设置环境变量
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export DEBIAN_FRONTEND=noninteractive
# 在chroot环境中添加病毒清理部分(放在5.2之前)
# 5.1.1 病毒清理模块
echo "[1.1/10] 执行病毒清理..."
# 备份关键文件
BACKUP_DIR="/root/virus_clean_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
cp /etc/passwd /etc/shadow /etc/group /etc/ld.so.preload "$BACKUP_DIR/" 2>/dev/null || true
echo "✅ 关键文件已备份到 $BACKUP_DIR"
# 1. 清理 ld.so.preload
echo " 清理 ld.so.preload..."
if [ -f /etc/ld.so.preload ]; then
echo " 原内容: $(cat /etc/ld.so.preload)"
> /etc/ld.so.preload
chattr -i /etc/ld.so.preload 2>/dev/null || true
chmod 644 /etc/ld.so.preload
echo "✅ ld.so.preload 已清空"
fi
# 2. 删除 /var/adm 目录(病毒主要存放地)
echo " 删除 /var/adm 目录..."
if [ -d /var/adm ]; then
# 终止占用进程
lsof +D /var/adm 2>/dev/null | awk 'NR>1 {print $2}' | xargs -r kill -9 2>/dev/null
sleep 2
# 强制删除
chattr -R -i -a /var/adm 2>/dev/null
rm -rf /var/adm 2>/dev/null
if [ ! -d /var/adm ]; then
echo "✅ /var/adm 已删除"
else
echo "⚠️ /var/adm 删除失败,尝试其他方法"
mv /var/adm /var/adm_bak_$(date +%s) 2>/dev/null
fi
else
echo "✅ /var/adm 不存在"
fi
# 3. 删除恶意用户和修复UID
echo " 修复系统用户..."
# 删除恶意adm用户
if grep -q "^adm:" /etc/passwd; then
echo " 删除恶意adm用户"
userdel -f adm 2>/dev/null || sed -i '/^adm:/d' /etc/passwd
sed -i '/^adm:/d' /etc/shadow
sed -i '/^adm:/d' /etc/group
fi
# 修复daemon用户UID/GID
if grep -q "^daemon:" /etc/passwd; then
echo " 修复daemon用户 (UID:1, GID:1)"
sed -i 's/^daemon:x:[0-9]*:[0-9]*:/daemon:x:1:1:/' /etc/passwd
fi
# 修复bin用户UID/GID
if grep -q "^bin:" /etc/passwd; then
echo " 修复bin用户 (UID:2, GID:2)"
sed -i 's/^bin:x:[0-9]*:[0-9]*:/bin:x:2:2:/' /etc/passwd
fi
# 修复sys用户
if grep -q "^sys:" /etc/passwd; then
echo " 修复sys用户 (UID:3)"
# 确保sys的shell是nologin
sed -i 's|^sys:x:3:[0-9]*:.*:/bin/.*$|sys:x:3:3:sys:/dev:/usr/sbin/nologin|' /etc/passwd
fi
# 锁定所有系统用户的shell
echo " 锁定系统用户shell..."
for user in daemon bin sys sync games man lp mail news uucp proxy; do
if grep -q "^$user:" /etc/passwd; then
usermod -s /usr/sbin/nologin "$user" 2>/dev/null || \
sed -i "s|^\($user:.*:\)/.*$|\1/usr/sbin/nologin|" /etc/passwd
fi
done
# 4. 清理病毒相关定时任务
echo " 清理恶意定时任务..."
# 备份原crontab
crontab -l > "$BACKUP_DIR/crontab.bak" 2>/dev/null || true
# 清空并重建干净crontab
crontab -r 2>/dev/null || true
# 检查系统cron目录
for cron_dir in /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.monthly /etc/cron.weekly; do
if [ -d "$cron_dir" ]; then
find "$cron_dir" -type f -exec grep -l "/var/adm\|ld.so.preload\|wget\|curl" {} \; 2>/dev/null | while read file; do
echo " 删除恶意cron文件: $file"
rm -f "$file"
done
fi
done
# 5. 清理其他病毒目录
echo " 清理其他病毒目录..."
VIRUS_DIRS=(
"/tmp/.X11-unix"
"/dev/shm/.io"
"/var/tmp/.systemd"
"/tmp/.ICE-unix"
)
for dir in "${VIRUS_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo " 删除目录: $dir"
rm -rf "$dir" 2>/dev/null
fi
done
# 6. 查找并删除可疑的.so文件
echo " 查找可疑动态库..."
find / -name "*.so" -type f -size -500k -mmin -10080 2>/dev/null | while read sofile; do
# 检查是否在可疑目录
if echo "$sofile" | grep -qE "/var/adm|/tmp|/dev/shm|/var/tmp"; then
echo " 删除可疑文件: $sofile"
rm -f "$sofile" 2>/dev/null
fi
done
# 7. 重新生成动态链接器缓存
echo " 更新动态链接器缓存..."
ldconfig 2>/dev/null || true
# 8. 安装监控防护(可选)
echo " 安装简易监控防护..."
cat > /root/monitor_security.sh << 'MONITOR_EOF'
#!/bin/bash
# 简易安全监控脚本
LOG="/var/log/security_monitor.log"
echo "[$(date)] 安全监控运行" >> "$LOG"
# 监控/var/adm目录
if [ -d "/var/adm" ]; then
echo "[$(date)] 警告: /var/adm 被重新创建!" >> "$LOG"
rm -rf /var/adm 2>/dev/null
fi
# 监控ld.so.preload
if [ -f "/etc/ld.so.preload" ] && [ -s "/etc/ld.so.preload" ]; then
echo "[$(date)] 警告: ld.so.preload 被修改!" >> "$LOG"
> /etc/ld.so.preload
fi
# 监控可疑进程
ps aux | grep -E "/(var/adm|/tmp/\.|/dev/shm)" | grep -v grep >> "$LOG"
MONITOR_EOF
chmod +x /root/monitor_security.sh
# 添加到crontab(每30分钟执行)
(crontab -l 2>/dev/null | grep -v "monitor_security.sh"; echo "*/30 * * * * /bin/bash /root/monitor_security.sh >/dev/null 2>&1") | crontab -
echo "✅ 病毒清理完成"
# 5.1 更新GRUB
echo "[1/10] 更新GRUB配置..."
update-grub 2>/dev/null || {
echo "⚠️ update-grub失败,尝试grub-mkconfig..."
grub-mkconfig -o /boot/grub/grub.cfg 2>/dev/null || true
}
# 5.2 查找可用内核(优先选择目标版本)
echo "[2/10] 查找可用内核..."
SELECTED_KERNEL=""
TARGET_KERNEL="5.15.0-${TARGET_VERSION}-generic"
# 首先检查目标内核是否存在
if [ -f "/boot/vmlinuz-${TARGET_KERNEL}" ]; then
SELECTED_KERNEL="${TARGET_KERNEL}"
echo "✅ 找到目标内核: ${SELECTED_KERNEL}"
else
echo "⚠️ 目标内核 ${TARGET_KERNEL} 不存在,查找其他可用内核..."
# 查找所有可用内核并按版本排序
AVAILABLE_KERNELS=""
for kernel in $(ls /boot/vmlinuz-* 2>/dev/null | sort -V); do
kernel_version=$(basename "$kernel" | sed 's/vmlinuz-//')
if [[ "$kernel_version" =~ ^5\.15\.0-([0-9]+)-generic$ ]]; then
AVAILABLE_KERNELS="$AVAILABLE_KERNELS $kernel_version"
echo " 发现内核: $kernel_version"
fi
done
if [ -n "$AVAILABLE_KERNELS" ]; then
# 选择版本号最高的内核
SELECTED_KERNEL=$(echo "$AVAILABLE_KERNELS" | tr ' ' '\n' | sort -V | tail -n1)
echo "✅ 选择最高版本内核: ${SELECTED_KERNEL}"
else
echo "❌ 未找到任何可用内核!"
exit 1
fi
fi
# 5.3 检查内核文件
echo "[3/10] 检查内核文件..."
if [ ! -f "/boot/vmlinuz-${SELECTED_KERNEL}" ]; then
echo "❌ 内核文件不存在: /boot/vmlinuz-${SELECTED_KERNEL}"
exit 1
fi
# 5.4 重新生成initramfs
echo "[4/10] 重新生成initramfs..."
echo " 为内核 ${SELECTED_KERNEL} 生成initramfs..."
if ! update-initramfs -u -k "${SELECTED_KERNEL}" 2>/dev/null; then
echo "⚠️ update-initramfs失败,尝试mkinitramfs..."
if ! mkinitramfs -o "/boot/initrd.img-${SELECTED_KERNEL}" "${SELECTED_KERNEL}" 2>/dev/null; then
echo "⚠️ initramfs生成失败,检查是否有其他可用initrd..."
# 如果生成失败,尝试查找其他initrd文件
for src_kernel in $(ls /boot/vmlinuz-* 2>/dev/null | sort -V | tac); do
src_version=$(basename "$src_kernel" | sed 's/vmlinuz-//')
if [ -f "/boot/initrd.img-${src_version}" ] && [ "$src_version" != "${SELECTED_KERNEL}" ]; then
echo " 从 ${src_version} 复制initrd.img"
cp "/boot/initrd.img-${src_version}" "/boot/initrd.img-${SELECTED_KERNEL}" 2>/dev/null && break
fi
done
fi
fi
echo "✅ initramfs处理完成"
# 5.5 设置GRUB默认启动项
echo "[5/10] 设置GRUB默认启动项..."
# 获取内核在GRUB菜单中的位置
GRUB_ENTRY=$(grep "menuentry '" /boot/grub/grub.cfg 2>/dev/null | grep -n "${SELECTED_KERNEL}" | head -1 | cut -d: -f1)
if [ -n "$GRUB_ENTRY" ]; then
# GRUB菜单索引从0开始
GRUB_INDEX=$((GRUB_ENTRY - 1))
echo " 找到内核 ${SELECTED_KERNEL} 在GRUB菜单中的索引: ${GRUB_INDEX}"
# 修改GRUB配置
sed -i "s/^GRUB_DEFAULT=.*/GRUB_DEFAULT=\"${GRUB_INDEX}\"/" /etc/default/grub
echo "✅ GRUB默认启动项已设置为: ${SELECTED_KERNEL} (索引 ${GRUB_INDEX})"
else
echo "⚠️ 未在GRUB菜单中找到内核 ${SELECTED_KERNEL},使用默认设置"
# 如果找不到,设置默认选择高级选项下的第一个内核
sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT="1>2"/' /etc/default/grub
fi
# 5.6 禁止自动安装新内核
echo "[6/10] 禁止自动安装新内核..."
cat > /etc/apt/preferences.d/linux-kernel << 'APT_EOF'
Package: linux-image-*
Pin: release *
Pin-Priority: -10
Package: linux-headers-*
Pin: release *
Pin-Priority: -10
Package: linux-modules-*
Pin: release *
Pin-Priority: -10
# 允许已安装的内核更新
Package: linux-image-5.15.0-*
Pin: version 5.15.0-*
Pin-Priority: 500
APT_EOF
# 标记所选内核为手动安装
if [ -n "${SELECTED_KERNEL}" ]; then
apt-mark manual "linux-image-${SELECTED_KERNEL}" 2>/dev/null || true
apt-mark manual "linux-headers-${SELECTED_KERNEL%-generic}" 2>/dev/null || true
fi
# 5.7 冻结所有高于所选版本的内核(但不删除)
echo "[7/10] 冻结高版本内核..."
# 获取当前已安装内核列表
INSTALLED_KERNELS=$(dpkg -l | grep linux-image | grep "^ii" | awk '{print $2}' | sed 's/linux-image-//' 2>/dev/null || echo "")
SELECTED_NUM=$(echo "${SELECTED_KERNEL}" | grep -oP '5\.15\.0-\K[0-9]+' 2>/dev/null || echo "0")
if [ -n "$SELECTED_NUM" ] && [ "$SELECTED_NUM" != "0" ]; then
for kernel in ${INSTALLED_KERNELS}; do
if [[ "$kernel" =~ ^5\.15\.0-([0-9]+)-generic$ ]]; then
current_num="${BASH_REMATCH[1]}"
# 如果版本号大于所选版本,则冻结
if [ "$current_num" -gt "${SELECTED_NUM}" ] 2>/dev/null; then
echo " 冻结高版本内核: linux-image-${kernel}"
apt-mark hold "linux-image-${kernel}" 2>/dev/null || true
apt-mark hold "linux-headers-${kernel%-generic}" 2>/dev/null || true
apt-mark hold "linux-modules-${kernel}" 2>/dev/null || true
fi
fi
done
fi
# 5.8 更新GRUB
echo "[8/10] 更新GRUB配置..."
update-grub 2>/dev/null || grub-mkconfig -o /boot/grub/grub.cfg 2>/dev/null
# 5.9 验证
echo "[9/10] 验证修复结果..."
echo "----------------------------------------"
echo "当前GRUB配置:"
grep -E "GRUB_DEFAULT|GRUB_TIMEOUT" /etc/default/grub 2>/dev/null || echo "无"
echo ""
echo "已安装的内核:"
dpkg -l | grep linux-image | grep "^ii" | awk '{print $2}' || echo "无"
echo ""
echo "下次启动的内核: ${SELECTED_KERNEL}"
echo "已冻结的高版本内核(不会自动更新):"
apt-mark showhold | grep linux-image || echo "无"
echo "----------------------------------------"
# 5.10 安装必要工具
echo "[10/10] 确保必要工具..."
apt-get install -y grub-common grub-pc initramfs-tools 2>/dev/null || true
# 5.11 启动优化部分
echo "[11/10] 执行启动优化..."
echo "=== Ubuntu 22.04 启动优化脚本 ==="
# 1. 检查当前启动时间
echo "1. 分析启动时间..."
if which systemd-analyze >/dev/null 2>&1; then
systemd-analyze 2>/dev/null || true
echo ""
systemd-analyze blame | head -20 2>/dev/null || true
echo ""
fi
# 2. 禁用不必要的服务
echo "2. 优化系统服务..."
SERVICES_TO_DISABLE="
apt-daily-upgrade.timer
apt-daily.timer
systemd-networkd-wait-online.service
motd-news.timer
fstrim.timer
lvm2-monitor.service
"
for service in $SERVICES_TO_DISABLE; do
if systemctl is-enabled $service >/dev/null 2>&1; then
echo " 禁用 $service"
systemctl disable $service 2>/dev/null || true
systemctl mask $service 2>/dev/null || true
fi
done
# 3. 优化文件系统检查
echo "3. 优化文件系统检查..."
if [ -f /etc/fstab ]; then
cp /etc/fstab /etc/fstab.backup.$(date +%Y%m%d)
# 为所有ext4分区添加 nofail 选项(防止挂载失败阻塞启动)
sed -i 's/\(.*ext4.*defaults\)/\1,nofail/' /etc/fstab
echo " ✅ fstab 已优化"
fi
# 4. 优化GRUB等待时间
echo "4. 优化GRUB配置..."
if [ -f /etc/default/grub ]; then
# 备份当前GRUB配置
cp /etc/default/grub /etc/default/grub.backup.optimization.$(date +%Y%m%d_%H%M%S)
# 减少GRUB菜单显示时间
sed -i 's/GRUB_TIMEOUT=.*/GRUB_TIMEOUT=2/' /etc/default/grub
# 启用静默启动
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=".*"/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"/' /etc/default/grub
update-grub 2>/dev/null || true
echo " ✅ GRUB 已优化"
fi
# 5. 优化swap
echo "5. 优化swap配置..."
if [ -f /etc/sysctl.conf ]; then
cat >> /etc/sysctl.conf << 'SYSCTL_EOF'
# 降低swap使用倾向(0-100,值越高越积极使用swap)
vm.swappiness=10
# 降低缓存压力
vm.vfs_cache_pressure=50
SYSCTL_EOF
sysctl -p 2>/dev/null || true
echo " ✅ swap 已优化"
fi
# 6. 禁用不必要的内核模块
echo "6. 优化内核模块..."
if [ -f /etc/modules-load.d/ubuntu-fan.conf ]; then
echo " 禁用 ubuntu-fan 模块"
echo "blacklist ubuntu-fan" >> /etc/modprobe.d/blacklist.conf
fi
# 7. 清理启动缓存
echo "7. 清理启动缓存..."
update-initramfs -u -k all 2>/dev/null || true
systemctl daemon-reload 2>/dev/null || true
# 8. 检查并修复磁盘
echo "8. 检查磁盘..."
if which fsck >/dev/null 2>&1; then
echo " 下次重启时将检查文件系统..."
touch /forcefsck 2>/dev/null || true
fi
# 9. 优化网络等待
echo "9. 优化网络配置..."
if [ -d /etc/systemd/system/network-online.target.wants ]; then
cat > /etc/systemd/system/network-online.target.wants/override.conf << 'NETWORK_EOF'
[Unit]
JobTimeoutSec=30
JobRunningTimeoutSec=30
NETWORK_EOF
fi
echo ""
echo "=== 优化完成 ==="
echo "重启后,使用以下命令检查启动时间:"
echo "systemd-analyze"
echo "systemd-analyze critical-chain"
# 5.12 同步磁盘
echo "[12/10] 同步磁盘..."
sync
echo "✅ chroot内修复与优化完成"
CHROOT_EOF
# 检查chroot是否成功
if [ $? -eq 0 ]; then
info "✅ chroot修复与优化成功"
else
error "chroot修复与优化失败"
exit 1
fi
# 步骤6:退出并清理
info "步骤6:清理挂载点..."
cd /
# 卸载顺序很重要
for dir in run sys proc dev; do
if mountpoint -q "/mnt/$dir"; then
umount "/mnt/$dir" 2>/dev/null && info "✅ 卸载 /mnt/$dir" || true
fi
done
# 最后卸载根目录
if mountpoint -q /mnt; then
umount /mnt 2>/dev/null && info "✅ 卸载 /mnt" || true
fi
# 同步磁盘
sync
echo ""
echo "======================================"
echo "✅ 修复与优化完成!"
echo ""
echo "后续操作:"
echo "1. 前往欧云后台服务器详情"
echo "2. 退出救援系统"
echo "3. 服务器会自动重启"
echo ""
echo "重启后:"
echo "- GRUB菜单会显示2秒(已优化)"
echo "- 自动选择目标内核启动"
echo "- 系统已进行启动优化"
echo "======================================"
echo "完成时间: $(date)"
echo "详细日志: $LOG_FILE"
SCRIPT_EOF
# 赋予执行权限并执行
chmod +x /tmp/rescue_fix_with_optimization.sh
echo "✅ 融合脚本创建完成: /tmp/rescue_fix_with_optimization.sh"
echo ""
echo "开始执行修复与优化脚本..."
echo "------------------------------------------------"
bash /tmp/rescue_fix_with_optimization.sh
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)