Debian服务器无人值守自动更新脚本

原创内容,转载请注明出处:https://www.myzhenai.com.cn/post/5033.html

前些天,Linux系统接连曝出了几个高危漏洞,甚至有内核漏洞,因为有时候我们在遇到这些漏洞的时候,不能及时更新系统

这将给我们的服务器带来末知的危险

所以我这里写了一个无人值守,自动更新的Shell脚本

脚本的原理是,定时自动 apt update && apt upgrade

但是脚本还可以判断系统中的Kernel数量,只保留最近的两个内核,其他的就卸载删除了

同时会自动清理不用的依赖文件包,这个脚本deepin系统慎用

因为,在deepin下,apt autoremove 会卸载很多关联的依赖,造成系统崩溃

将脚本复制到服务器上,保存为.sh后缀的文件

然后,crontab -e 设置定时任务,让脚本定时执行就可以了

以后,就算自己不登录服务器,服务器也会自动更新

#!/bin/bash
set -eu

#############################################################################
# Debian 12 服务器自动更新脚本(无人值守版)
# 功能:更新系统、升级内核、自动检测并删除旧内核
# 作者:RucLinux
#############################################################################

# 配置区域
LOG_FILE="/var/log/debian-update.log"
KEEP_KERNEL_COUNT=2               # 保留的内核数量(包括当前使用的)

# 日志函数(无颜色,适合文件记录)
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

error_exit() {
    log_message "错误: $1"
    exit 1
}

# 检查是否以 root 运行
if [ "$EUID" -ne 0 ]; then
    error_exit "请以 root 用户运行此脚本"
fi

# 检查必要工具
check_tools() {
    log_message "检查必要工具..."
    local tools=("curl" "wget" "awk" "sed" "grep")
    for tool in "${tools[@]}"; do
        if ! command -v "$tool" &>/dev/null; then
            error_exit "缺少必要工具: $tool"
        fi
    done
    log_message "工具检查完成"
}

# 1. 更新软件包列表
update_package_list() {
    log_message "更新软件包列表..."
    apt update >>"$LOG_FILE" 2>&1 || error_exit "apt update 失败"
    log_message "软件包列表更新完成"
}

# 2. 升级已安装的软件包
upgrade_packages() {
    log_message "升级已安装软件包..."
    apt upgrade -y >>"$LOG_FILE" 2>&1 || error_exit "apt upgrade 失败"
    log_message "软件包升级完成"
}

# 3. 执行完整升级(包含依赖变化)
full_upgrade() {
    log_message "执行完整升级..."
    apt full-upgrade -y >>"$LOG_FILE" 2>&1 || error_exit "apt full-upgrade 失败"
    log_message "完整升级完成"
}

# 4. 清理不再需要的包
clean_unused_packages() {
    log_message "清理不再需要的包..."
    apt autoremove --purge -y >>"$LOG_FILE" 2>&1 || log_message "警告: autoremove 执行失败"
    apt autoclean -y >>"$LOG_FILE" 2>&1 || log_message "警告: autoclean 执行失败"
    apt clean -y >>"$LOG_FILE" 2>&1 || log_message "警告: clean 执行失败"
    log_message "包清理完成"
}

# 5. 自动删除旧内核(核心功能)
remove_old_kernels() {
    log_message "开始清理旧内核..."

    # 获取当前运行的内核版本(如 6.1.0-18-amd64 取 6.1.0-18)
    local current_kernel=$(uname -r | cut -d'-' -f1,2)
    log_message "当前运行的内核: $current_kernel"

    # 获取所有已安装的内核包列表(按版本排序)
    local kernel_packages=$(dpkg -l | awk '/^ii  linux-image-[0-9]/{print $2}' | sort -V)

    if [ -z "$kernel_packages" ]; then
        log_message "没有找到内核包"
        return 0
    fi

    local total_kernels=$(echo "$kernel_packages" | wc -l)
    local kernels_to_remove=$((total_kernels - KEEP_KERNEL_COUNT))

    if [ $kernels_to_remove -le 0 ]; then
        log_message "当前内核数量 ($total_kernels) 未超过保留数量 ($KEEP_KERNEL_COUNT),无需清理"
        return 0
    fi

    log_message "发现 $total_kernels 个内核包,将保留最新的 $KEEP_KERNEL_COUNT 个"

    # 找出要删除的内核(最旧的几个)
    local kernels_to_delete=$(echo "$kernel_packages" | head -n $kernels_to_remove)

    log_message "以下内核将被删除:"
    echo "$kernels_to_delete" | while read kernel; do
        log_message "  - $kernel"
    done

    # 执行删除(跳过当前运行的内核)
    echo "$kernels_to_delete" | while read kernel; do
        if [[ "$kernel" == *"$current_kernel"* ]]; then
            log_message "跳过当前运行的内核: $kernel"
            continue
        fi

        log_message "删除内核: $kernel"
        apt purge -y "$kernel" >>"$LOG_FILE" 2>&1 || log_message "警告: 删除 $kernel 失败"

        # 删除相关的模块目录
        local kernel_version=$(echo "$kernel" | sed 's/linux-image-//')
        if [ -d "/lib/modules/$kernel_version" ]; then
            rm -rf "/lib/modules/$kernel_version"
            log_message "删除模块目录: /lib/modules/$kernel_version"
        fi

        # 删除/boot中的相关文件
        for file in /boot/vmlinuz-$kernel_version /boot/initrd.img-$kernel_version /boot/System.map-$kernel_version /boot/config-$kernel_version; do
            [ -f "$file" ] && rm -f "$file" && log_message "删除: $file"
        done
    done

    # 再次运行 autoremove 确保清理干净
    apt autoremove --purge -y >>"$LOG_FILE" 2>&1

    log_message "旧内核清理完成"

    # 更新 GRUB 配置
    if command -v update-grub &>/dev/null; then
        log_message "更新 GRUB 配置..."
        update-grub >>"$LOG_FILE" 2>&1
    fi
}

# 6. 清理临时文件和日志
clean_temp_files() {
    log_message "清理临时文件..."

    # 清理 /tmp 中超过7天的文件
    find /tmp -type f -atime +7 -delete 2>/dev/null || true

    # 清理 journal 日志,保留最近2周
    journalctl --vacuum-time=2weeks >>"$LOG_FILE" 2>&1 || true

    # 清理旧的日志文件
    find /var/log -name "*.log.*" -mtime +30 -delete 2>/dev/null || true
    find /var/log -name "*.gz" -mtime +30 -delete 2>/dev/null || true

    log_message "临时文件清理完成"
}

# 7. 检查是否需要重启(仅记录,不自动重启)
check_reboot_needed() {
    if [ -f /var/run/reboot-required ]; then
        log_message "系统需要重启以应用更新"
        cat /var/run/reboot-required 2>/dev/null | while read line; do
            log_message "  - $line"
        done
        log_message "请手动重启系统以完成更新"
    else
        log_message "无需重启"
    fi
}

# 8. 生成系统报告
generate_report() {
    log_message "生成系统报告..."

    local report_file="/tmp/system-report-$(date +%Y%m%d).txt"

    {
        echo "========================================="
        echo "Debian 12 系统更新报告"
        echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')"
        echo "========================================="
        echo ""
        echo "系统信息:"
        echo "  - 主机名: $(hostname)"
        echo "  - 内核版本: $(uname -r)"
        echo "  - 系统版本: $(lsb_release -d 2>/dev/null | cut -f2 || cat /etc/debian_version)"
        echo ""
        echo "磁盘使用情况:"
        df -h | grep -E '^/dev/' | while read line; do
            echo "  $line"
        done
        echo ""
        echo "已安装内核:"
        dpkg -l | awk '/^ii  linux-image-[0-9]/{print "  - " $2}' | sort -V
        echo ""
        echo "更新日志:"
        tail -20 "$LOG_FILE"
    } > "$report_file"

    log_message "系统报告已生成: $report_file"
}

# 主函数
main() {
    log_message "========== 开始 Debian 12 自动更新 =========="

    check_tools
    update_package_list
    upgrade_packages
    full_upgrade
    clean_unused_packages
    remove_old_kernels
    clean_temp_files
    generate_report
    check_reboot_needed

    log_message "========== Debian 12 自动更新完成 =========="
}

main "$@"

脚本会在/tmp/ 目录下生成一个txt的报告文件,如果有更新的话,会将更新的内容反馈回来,如果没有更新,就不反馈

root@dZ:~# cat /tmp/system-report-$(date +%Y%m%d).txt
=========================================
Debian 12 系统更新报告
生成时间: 2026-05-26 14:43:50
=========================================

系统信息:
  - 主机名: dZ
  - 内核版本: 6.1.0-48-amd64
  - 系统版本: Debian GNU/Linux 12 (bookworm)

磁盘使用情况:
  /dev/vda3        79G   26G   50G  34% /
  /dev/vda2       189M   12M  177M   7% /boot/efi

已安装内核:
  - linux-image-6.1.0-47-amd64
  - linux-image-6.1.0-48-amd64

更新日志:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

[2026-05-26 14:43:50] 包清理完成
[2026-05-26 14:43:50] 开始清理旧内核...
[2026-05-26 14:43:50] 当前运行的内核: 6.1.0-48
[2026-05-26 14:43:50] 当前内核数量 (2) 未超过保留数量 (2),无需清理
[2026-05-26 14:43:50] 清理临时文件...
Vacuuming done, freed 0B of archived journals from /run/log/journal.
Vacuuming done, freed 0B of archived journals from /var/log/journal.
Deleted archived journal /var/log/journal/edfdedf5bc6d4c37b695d3cc884f6a78/system@54b6f1ef06be4fd482281ee1b4a4f8bf-00000000001b9e1a-000651974af965cd.journal (42.7M).
Vacuuming done, freed 42.7M of archived journals from /var/log/journal/edfdedf5bc6d4c37b695d3cc884f6a78.
[2026-05-26 14:43:50] 临时文件清理完成
[2026-05-26 14:43:50] 生成系统报告...

 

发布时 IP 属地:海南省海口市

标签:
IP 地址 216.73.216.217
区域位置 美国加利福尼亚洛杉矶
系统信息 🇨🇳 系统浏览器
最后修改:2026 年 05 月 26 日

赞赏支持

文章二维码