Update image.sh
This commit is contained in:
329
dev/image.sh
329
dev/image.sh
@@ -6,8 +6,10 @@
|
|||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[0;33m'
|
YELLOW='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# 检查 root 权限
|
||||||
check_root() {
|
check_root() {
|
||||||
if [ "$(id -u)" -ne 0 ]; then
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
echo -e "${RED}错误:必须使用 root 权限运行此脚本${NC}"
|
echo -e "${RED}错误:必须使用 root 权限运行此脚本${NC}"
|
||||||
@@ -15,46 +17,122 @@ check_root() {
|
|||||||
fi
|
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() {
|
check_cloud_kernel() {
|
||||||
if ! uname -r | grep -q 'cloud'; then
|
if ! uname -r | grep -q 'cloud'; then
|
||||||
echo -e "${GREEN}提示:系统已在标准内核运行 ($(uname -r))${NC}"
|
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
|
exit 0
|
||||||
fi
|
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 image_pkg="linux-image-amd64"
|
||||||
local headers_pkg="linux-headers-amd64"
|
local headers_pkg="linux-headers-amd64"
|
||||||
|
|
||||||
@@ -62,66 +140,163 @@ force_install_standard() {
|
|||||||
image_pkg="linux-image-generic"
|
image_pkg="linux-image-generic"
|
||||||
headers_pkg="linux-headers-generic"
|
headers_pkg="linux-headers-generic"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 强制安装并跳过配置提问
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt install -y --reinstall --allow-downgrades \
|
|
||||||
"$image_pkg" "$headers_pkg"
|
|
||||||
|
|
||||||
# 确保 initramfs 更新
|
echo -e "正在安装 $image_pkg $headers_pkg ..."
|
||||||
local std_kernel=$(ls /boot/vmlinuz-* | grep -v cloud | sort -V | tail -1 | sed 's|/boot/vmlinuz-||')
|
|
||||||
update-initramfs -u -k "$std_kernel"
|
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() {
|
# 卸载所有 Cloud 内核
|
||||||
echo -e "${YELLOW}步骤4/4:重建 GRUB...${NC}"
|
remove_cloud_kernels() {
|
||||||
|
echo -e "${YELLOW}[2/5] 卸载所有 Cloud 内核${NC}"
|
||||||
|
|
||||||
# 备份原配置
|
# 找出所有 Cloud 内核包(包括 image 和 headers)
|
||||||
mkdir -p /root/grub_backup
|
local cloud_pkgs=$(dpkg -l 2>/dev/null | awk '/linux-(image|headers|modules)-[0-9].*cloud/ {print $2}')
|
||||||
cp -a /boot/grub /root/grub_backup/grub.bak.$(date +%s)
|
|
||||||
|
|
||||||
# 生成干净的 GRUB 配置
|
if [ -z "$cloud_pkgs" ]; then
|
||||||
cat > /etc/default/grub <<'EOF'
|
echo -e "${YELLOW}未找到 Cloud 内核包${NC}"
|
||||||
GRUB_DEFAULT=0
|
return 0
|
||||||
GRUB_TIMEOUT=5
|
fi
|
||||||
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
|
|
||||||
|
|
||||||
# 确保使用第一个菜单项
|
echo -e "正在卸载以下包:"
|
||||||
grub-set-default 0
|
echo "$cloud_pkgs" | sed 's/^/ /'
|
||||||
update-grub
|
|
||||||
|
|
||||||
# 特殊处理 UEFI 系统
|
# 解锁所有 Cloud 内核
|
||||||
if [ -d /sys/firmware/efi ]; then
|
apt-mark unhold $cloud_pkgs > /dev/null 2>&1
|
||||||
echo -e "检测到 UEFI 系统,更新引导加载程序..."
|
|
||||||
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck
|
# 彻底卸载
|
||||||
|
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
|
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() {
|
main() {
|
||||||
echo -e "\n${GREEN}=== Debian/Ubuntu 内核切换脚本 ===${NC}"
|
echo -e "\n${GREEN}Debian/Ubuntu 内核切换脚本${NC}\n"
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
check_cloud_kernel
|
check_cloud_kernel
|
||||||
|
confirm_operation
|
||||||
|
|
||||||
# 执行核心修复步骤
|
change_mirrors
|
||||||
purge_cloud_kernel
|
install_standard_kernel
|
||||||
lock_cloud_kernel
|
remove_cloud_kernels
|
||||||
force_install_standard
|
configure_grub
|
||||||
nuclear_grub_update
|
update_grub_config
|
||||||
|
verify_configuration
|
||||||
|
|
||||||
# 最终验证
|
echo -e "\n${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
echo -e "\n${GREEN}=== 操作完成 ===${NC}"
|
echo -e "${GREEN}操作完成!${NC}"
|
||||||
echo -e "请手动重启系统:"
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
echo -e "1. 重启系统: ${YELLOW}reboot${NC}"
|
echo -e "\n${YELLOW}重要提示:${NC}"
|
||||||
echo -e "2. 检查内核: ${YELLOW}uname -r${NC}"
|
echo -e " • 所有 Cloud 内核已卸载"
|
||||||
|
echo -e " • 备份位置:${BLUE}/root/grub_backup/${NC}\n"
|
||||||
touch /root/.kernel_switch_success
|
|
||||||
|
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 "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user