Update image.sh
This commit is contained in:
329
dev/image.sh
329
dev/image.sh
@@ -6,8 +6,10 @@
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 检查 root 权限
|
||||
check_root() {
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e "${RED}错误:必须使用 root 权限运行此脚本${NC}"
|
||||
@@ -15,46 +17,122 @@ check_root() {
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测地理位置
|
||||
detect_region() {
|
||||
echo -e "${BLUE}检测网络位置...${NC}"
|
||||
|
||||
local TRACE_URLS=(
|
||||
"https://www.cloudflare.com/cdn-cgi/trace"
|
||||
"https://www.visa.cn/cdn-cgi/trace"
|
||||
)
|
||||
|
||||
local trace_info=""
|
||||
for url in "${TRACE_URLS[@]}"; do
|
||||
trace_info=$(curl -sSL --max-time 8 "$url" 2>/dev/null) && break
|
||||
done
|
||||
|
||||
if echo "$trace_info" | grep -q '^loc=CN'; then
|
||||
echo -e "${GREEN}CN 网络环境${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${GREEN}非 CN 网络环境${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 切换软件源
|
||||
change_mirrors() {
|
||||
echo -e "${YELLOW}[0/5] 配置软件源${NC}"
|
||||
|
||||
if detect_region; then
|
||||
echo -e "使用阿里云镜像..."
|
||||
bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) \
|
||||
--source mirrors.aliyun.com \
|
||||
--protocol http \
|
||||
--use-intranet-source false \
|
||||
--install-epel true \
|
||||
--backup true \
|
||||
--upgrade-software false \
|
||||
--clean-cache false \
|
||||
--ignore-backup-tips \
|
||||
--pure-mode
|
||||
else
|
||||
echo -e "使用官方源..."
|
||||
bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) \
|
||||
--use-official-source true \
|
||||
--protocol http \
|
||||
--use-intranet-source false \
|
||||
--install-epel true \
|
||||
--backup true \
|
||||
--upgrade-software false \
|
||||
--clean-cache false \
|
||||
--ignore-backup-tips \
|
||||
--pure-mode
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${YELLOW}警告:软件源切换失败,继续使用当前源${NC}"
|
||||
else
|
||||
apt update -qq
|
||||
fi
|
||||
}
|
||||
|
||||
# 二次确认
|
||||
confirm_operation() {
|
||||
echo -e "\n${RED}⚠️ 高危操作警告 ⚠️${NC}"
|
||||
echo -e "${RED}此脚本将修改系统内核,可能导致:${NC}"
|
||||
echo -e "${RED} • 系统无法启动(如果新内核不兼容)${NC}"
|
||||
echo -e "${RED} • 网络驱动丢失(在特定云平台上)${NC}"
|
||||
echo -e "${RED} • 需要控制台访问权限才能恢复${NC}"
|
||||
echo -e "${RED} • 请务必备份重要数据再执行${NC}"
|
||||
echo -e "\n${YELLOW}当前内核:${NC}$(uname -r)"
|
||||
echo -e "${YELLOW}虚拟化:${NC}$(systemd-detect-virt 2>/dev/null || echo '未知')"
|
||||
|
||||
# 显示将要删除的 Cloud 内核
|
||||
local cloud_pkgs=$(dpkg -l 2>/dev/null | awk '/linux-(image|headers)-[0-9].*cloud/ {print $2}')
|
||||
if [ -n "$cloud_pkgs" ]; then
|
||||
echo -e "\n${YELLOW}将要卸载的 Cloud 内核:${NC}"
|
||||
echo "$cloud_pkgs" | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
echo ""
|
||||
read -p "$(echo -e ${YELLOW}"确认继续?[y/N]: "${NC})" confirm
|
||||
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${GREEN}操作已取消${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}开始执行...${NC}\n"
|
||||
}
|
||||
|
||||
# 检查当前内核
|
||||
check_cloud_kernel() {
|
||||
if ! uname -r | grep -q 'cloud'; then
|
||||
echo -e "${GREEN}提示:系统已在标准内核运行 ($(uname -r))${NC}"
|
||||
|
||||
# 检查是否还有 Cloud 内核包
|
||||
local cloud_pkgs=$(dpkg -l 2>/dev/null | awk '/linux-(image|headers)-[0-9].*cloud/ {print $2}')
|
||||
if [ -n "$cloud_pkgs" ]; then
|
||||
echo -e "${YELLOW}但系统中仍有 Cloud 内核包:${NC}"
|
||||
echo "$cloud_pkgs" | sed 's/^/ /'
|
||||
echo ""
|
||||
read -p "$(echo -e ${YELLOW}"是否清理这些包?[y/N]: "${NC})" clean_confirm
|
||||
if [[ "$clean_confirm" =~ ^[Yy]$ ]]; then
|
||||
apt purge -y $cloud_pkgs
|
||||
apt autoremove -y --purge
|
||||
update-grub
|
||||
echo -e "${GREEN}清理完成${NC}"
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
purge_cloud_kernel() {
|
||||
echo -e "${YELLOW}步骤1/4:彻底移除 Cloud 内核...${NC}"
|
||||
# 安装标准内核
|
||||
install_standard_kernel() {
|
||||
echo -e "${YELLOW}[1/5] 安装标准内核${NC}"
|
||||
|
||||
# 找出所有 Cloud 内核包
|
||||
local cloud_pkgs=$(dpkg -l | awk '/linux-(image|headers)-[0-9].*cloud/ {print $2}')
|
||||
|
||||
if [ -n "$cloud_pkgs" ]; then
|
||||
echo -e "正在卸载: ${cloud_pkgs}"
|
||||
apt purge -y $cloud_pkgs
|
||||
apt autoremove -y --purge
|
||||
else
|
||||
echo -e "${GREEN}提示:未找到 Cloud 内核包${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
lock_cloud_kernel() {
|
||||
echo -e "${YELLOW}步骤2/4:锁定 Cloud 内核...${NC}"
|
||||
|
||||
# 检查是否还有额外的 Cloud 内核包,如果有则标记为 hold
|
||||
cloud_kernels=$(apt list --installed 2>/dev/null | grep -i 'linux-image' | grep -i 'cloud' | cut -d'/' -f1)
|
||||
|
||||
if [ -n "$cloud_kernels" ]; then
|
||||
echo "找到以下 Cloud 内核包,正在锁定:$cloud_kernels"
|
||||
apt-mark hold $cloud_kernels
|
||||
else
|
||||
echo -e "${GREEN}提示:未找到任何 Cloud 内核包,跳过锁定步骤。${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
force_install_standard() {
|
||||
echo -e "${YELLOW}步骤3/4:安装标准内核...${NC}"
|
||||
|
||||
# 根据系统类型选择包名
|
||||
local image_pkg="linux-image-amd64"
|
||||
local headers_pkg="linux-headers-amd64"
|
||||
|
||||
@@ -62,66 +140,163 @@ force_install_standard() {
|
||||
image_pkg="linux-image-generic"
|
||||
headers_pkg="linux-headers-generic"
|
||||
fi
|
||||
|
||||
# 强制安装并跳过配置提问
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y --reinstall --allow-downgrades \
|
||||
"$image_pkg" "$headers_pkg"
|
||||
|
||||
# 确保 initramfs 更新
|
||||
local std_kernel=$(ls /boot/vmlinuz-* | grep -v cloud | sort -V | tail -1 | sed 's|/boot/vmlinuz-||')
|
||||
update-initramfs -u -k "$std_kernel"
|
||||
echo -e "正在安装 $image_pkg $headers_pkg ..."
|
||||
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y --reinstall \
|
||||
"$image_pkg" "$headers_pkg" 2>&1 | grep -E "正在|Setting up|unpacking|Processing|配置|解包"
|
||||
|
||||
if [ ${PIPESTATUS[0]} -ne 0 ]; then
|
||||
echo -e "${RED}错误:标准内核安装失败!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local std_kernel=$(ls /boot/vmlinuz-* 2>/dev/null | grep -v cloud | sort -V | tail -1 | sed 's|/boot/vmlinuz-||')
|
||||
if [ -n "$std_kernel" ]; then
|
||||
echo -e "更新 initramfs: $std_kernel"
|
||||
update-initramfs -u -k "$std_kernel" 2>&1 | grep -v "^I:"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ 标准内核安装完成: $std_kernel${NC}"
|
||||
}
|
||||
|
||||
nuclear_grub_update() {
|
||||
echo -e "${YELLOW}步骤4/4:重建 GRUB...${NC}"
|
||||
# 卸载所有 Cloud 内核
|
||||
remove_cloud_kernels() {
|
||||
echo -e "${YELLOW}[2/5] 卸载所有 Cloud 内核${NC}"
|
||||
|
||||
# 备份原配置
|
||||
mkdir -p /root/grub_backup
|
||||
cp -a /boot/grub /root/grub_backup/grub.bak.$(date +%s)
|
||||
# 找出所有 Cloud 内核包(包括 image 和 headers)
|
||||
local cloud_pkgs=$(dpkg -l 2>/dev/null | awk '/linux-(image|headers|modules)-[0-9].*cloud/ {print $2}')
|
||||
|
||||
# 生成干净的 GRUB 配置
|
||||
cat > /etc/default/grub <<'EOF'
|
||||
GRUB_DEFAULT=0
|
||||
GRUB_TIMEOUT=5
|
||||
GRUB_DISTRIBUTOR=lsb_release -i -s 2> /dev/null || echo Debian
|
||||
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
|
||||
GRUB_CMDLINE_LINUX=""
|
||||
GRUB_DISABLE_OS_PROBER=true
|
||||
GRUB_DISABLE_RECOVERY=true
|
||||
EOF
|
||||
|
||||
# 完全重建配置
|
||||
grub-mkconfig -o /boot/grub/grub.cfg
|
||||
if [ -z "$cloud_pkgs" ]; then
|
||||
echo -e "${YELLOW}未找到 Cloud 内核包${NC}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 确保使用第一个菜单项
|
||||
grub-set-default 0
|
||||
update-grub
|
||||
echo -e "正在卸载以下包:"
|
||||
echo "$cloud_pkgs" | sed 's/^/ /'
|
||||
|
||||
# 特殊处理 UEFI 系统
|
||||
if [ -d /sys/firmware/efi ]; then
|
||||
echo -e "检测到 UEFI 系统,更新引导加载程序..."
|
||||
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck
|
||||
# 解锁所有 Cloud 内核
|
||||
apt-mark unhold $cloud_pkgs > /dev/null 2>&1
|
||||
|
||||
# 彻底卸载
|
||||
DEBIAN_FRONTEND=noninteractive apt purge -y $cloud_pkgs 2>&1 | grep -E "正在|Removing|移除|卸载"
|
||||
|
||||
if [ ${PIPESTATUS[0]} -ne 0 ]; then
|
||||
echo -e "${YELLOW}警告:部分包卸载失败,继续执行...${NC}"
|
||||
fi
|
||||
|
||||
# 清理残留
|
||||
apt autoremove -y --purge > /dev/null 2>&1
|
||||
|
||||
# 验证是否清理干净
|
||||
local remaining=$(dpkg -l 2>/dev/null | awk '/linux-(image|headers|modules)-[0-9].*cloud/ {print $2}')
|
||||
if [ -n "$remaining" ]; then
|
||||
echo -e "${YELLOW}警告:以下包未能完全卸载:${NC}"
|
||||
echo "$remaining" | sed 's/^/ /'
|
||||
else
|
||||
echo -e "${GREEN}✓ 所有 Cloud 内核已卸载${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 配置 GRUB
|
||||
configure_grub() {
|
||||
echo -e "${YELLOW}[3/5] 配置 GRUB${NC}"
|
||||
|
||||
mkdir -p /root/grub_backup
|
||||
cp /etc/default/grub /root/grub_backup/grub.default.$(date +%s) 2>/dev/null
|
||||
|
||||
# 使用简单的 GRUB_DEFAULT=0
|
||||
cat > /etc/default/grub <<'EOF'
|
||||
GRUB_DEFAULT=0
|
||||
GRUB_TIMEOUT=5
|
||||
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
|
||||
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
|
||||
GRUB_CMDLINE_LINUX=""
|
||||
GRUB_DISABLE_OS_PROBER=true
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}✓ GRUB 配置完成(GRUB_DEFAULT=0)${NC}"
|
||||
}
|
||||
|
||||
# 更新 GRUB
|
||||
update_grub_config() {
|
||||
echo -e "${YELLOW}[4/5] 更新 GRUB${NC}"
|
||||
|
||||
cp -a /boot/grub /root/grub_backup/grub.bak.$(date +%s) 2>/dev/null
|
||||
|
||||
echo -e "重新生成 GRUB 配置..."
|
||||
update-grub 2>&1 | grep -E "Found|Generating|生成|找到"
|
||||
|
||||
# 明确设置默认启动项为 0
|
||||
grub-set-default 0
|
||||
|
||||
if [ -d /sys/firmware/efi ]; then
|
||||
echo -e "更新 UEFI 引导..."
|
||||
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ GRUB 更新完成,默认启动第一个内核${NC}"
|
||||
}
|
||||
|
||||
# 验证配置
|
||||
verify_configuration() {
|
||||
echo -e "${YELLOW}[5/5] 验证配置${NC}"
|
||||
|
||||
echo -e "${BLUE}当前内核:${NC}$(uname -r)"
|
||||
|
||||
echo -e "${BLUE}系统中的内核:${NC}"
|
||||
local all_kernels=$(dpkg -l 2>/dev/null | grep -E 'linux-image-[0-9]' | awk '{print $2}')
|
||||
if [ -n "$all_kernels" ]; then
|
||||
echo "$all_kernels" | sed 's/^/ /'
|
||||
else
|
||||
echo " 未找到内核包"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}GRUB 启动顺序(前3项):${NC}"
|
||||
awk -F "'" '/menuentry / && $0 !~ /submenu/ {
|
||||
count++
|
||||
if (count <= 3) {
|
||||
print " " count-1 ": " $2
|
||||
}
|
||||
}' /boot/grub/grub.cfg 2>/dev/null
|
||||
|
||||
echo -e "${BLUE}GRUB 默认设置:${NC} $(grep "^GRUB_DEFAULT=" /etc/default/grub)"
|
||||
|
||||
echo -e "${GREEN}✓ 验证完成${NC}"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "\n${GREEN}=== Debian/Ubuntu 内核切换脚本 ===${NC}"
|
||||
echo -e "\n${GREEN}Debian/Ubuntu 内核切换脚本${NC}\n"
|
||||
|
||||
check_root
|
||||
check_cloud_kernel
|
||||
confirm_operation
|
||||
|
||||
# 执行核心修复步骤
|
||||
purge_cloud_kernel
|
||||
lock_cloud_kernel
|
||||
force_install_standard
|
||||
nuclear_grub_update
|
||||
change_mirrors
|
||||
install_standard_kernel
|
||||
remove_cloud_kernels
|
||||
configure_grub
|
||||
update_grub_config
|
||||
verify_configuration
|
||||
|
||||
# 最终验证
|
||||
echo -e "\n${GREEN}=== 操作完成 ===${NC}"
|
||||
echo -e "请手动重启系统:"
|
||||
echo -e "1. 重启系统: ${YELLOW}reboot${NC}"
|
||||
echo -e "2. 检查内核: ${YELLOW}uname -r${NC}"
|
||||
|
||||
touch /root/.kernel_switch_success
|
||||
echo -e "\n${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${GREEN}操作完成!${NC}"
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "\n${YELLOW}重要提示:${NC}"
|
||||
echo -e " • 所有 Cloud 内核已卸载"
|
||||
echo -e " • 备份位置:${BLUE}/root/grub_backup/${NC}\n"
|
||||
|
||||
echo -e "${YELLOW}下一步:${NC}"
|
||||
echo -e " 1. 执行 ${BLUE}reboot${NC} 重启系统"
|
||||
echo -e " 2. 重启后运行 ${BLUE}uname -r${NC} 确认内核"
|
||||
|
||||
read -p "$(echo -e ${YELLOW}"立即重启?[y/N]: "${NC})" reboot_now
|
||||
if [[ "$reboot_now" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${GREEN}正在重启...${NC}"
|
||||
sleep 2
|
||||
reboot
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user