本文目录导读:

- 核心原理:非交互模式与自动确认
- 方案一:适用于Debian/Ubuntu系列
- 方案二:适用于RHEL/CentOS/Fedora/AlmaLinux/Rocky系列
- 方案三:适用于SUSE/openSUSE系列
- 最佳实践与安全考虑
- 如何使用这个脚本
在Shell脚本中自动安装安全补丁,核心是通过包管理器(如 apt、yum、dnf、zypper)的非交互模式执行更新命令。
以下是根据不同Linux发行版以及一些最佳实践编写的Shell脚本示例和说明。
核心原理:非交互模式与自动确认
DEBIAN_FRONTEND=noninteractive: 对于基于Debian的系统,这个环境变量可以防止安装过程中弹出发行版说明、配置文件替换等交互式对话框。-y或--assumeyes: 对所有包管理器的install、remove、update命令自动回答“yes”。--only-upgrade: 只升级已安装的包,不安装新增的依赖包(用于安全补丁时可选)。
适用于Debian/Ubuntu系列
此脚本仅更新安全相关的更新(适用于Ubuntu/Debian,依赖 unattended-upgrades 包)。
#!/bin/bash
LOG_FILE="/var/log/auto-patch.log"
# 检查是否为root用户
if [ "$(id -u)" -ne 0 ]; then
echo "错误:请以root用户运行此脚本。"
exit 1
fi
echo "[$(date)] 开始自动安装安全补丁..." >> $LOG_FILE
# 1. 更新软件包列表
echo "[$(date)] 更新软件包索引..." >> $LOG_FILE
apt-get update -qq >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "[$(date)] 错误:更新源失败。" >> $LOG_FILE
exit 1
fi
# 2. 执行安全更新(方法A:使用 unattended-upgrades)
# 这个方法更加精确,只安装安全更新,但需要先安装该包。
# apt-get install -y unattended-upgrades
# unattended-upgrades -v >> $LOG_FILE 2>&1
# 3. 执行安全更新(方法B:使用 apt-get 的 upgrade 命令并只升级安全相关的包)
# 更通用的方法,大多数Debian/Ubuntu系统默认支持。
echo "[$(date)] 安装安全更新..." >> $LOG_FILE
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -o Dpkg::Options::="--force-confnew" >> $LOG_FILE 2>&1
# -o Dpkg::Options::=“--force-confnew”:自动覆盖配置文件的本地修改(可选,请谨慎)。
# 检查是否成功
if [ $? -eq 0 ]; then
echo "[$(date)] 安全更新安装完成。" >> $LOG_FILE
else
echo "[$(date)] 错误:更新安装失败。" >> $LOG_FILE
exit 1
fi
# 4. (可选) 自动移除不再需要的依赖包
echo "[$(date)] 清理无用软件包..." >> $LOG_FILE
apt-get autoremove -y >> $LOG_FILE 2>&1
apt-get autoclean >> $LOG_FILE 2>&1
echo "[$(date)] 补丁安装流程结束。" >> $LOG_FILE
exit 0
更精确的安全更新(Ubuntu/Debian 推荐):
如果你希望只安装安全补丁,而不是所有更新,可以使用 unattended-upgrades:
# 先安装 apt-get install -y unattended-upgrades # 配置(通常位于 /etc/apt/apt.conf.d/50unattended-upgrades) # 确保下面这行没有被注释: # "origin=Ubuntu,archive=*-security"; # 执行 unattended-upgrades -v
适用于RHEL/CentOS/Fedora/AlmaLinux/Rocky系列
此脚本使用 yum 或 dnf 安装安全更新。
#!/bin/bash
LOG_FILE="/var/log/auto-patch.log"
# 检查是否为root用户
if [ "$(id -u)" -ne 0 ]; then
echo "错误:请以root用户运行此脚本。"
exit 1
fi
echo "[$(date)] 开始自动安装安全补丁..." >> $LOG_FILE
# 检测包管理器
if command -v dnf &> /dev/null; then
PKG_MGR="dnf"
elif command -v yum &> /dev/null; then
PKG_MGR="yum"
else
echo "错误:未找到 yum 或 dnf。" >> $LOG_FILE
exit 1
fi
# 1. 更新缓存
echo "[$(date)] 更新软件包缓存 ($PKG_MGR)..." >> $LOG_FILE
$PKG_MGR check-update --quiet >> $LOG_FILE 2>&1
# 注意:check-update 退出码为 100 时表示有可用更新,0表示没有,1表示出错。
# 2. 安装安全更新(关键命令)
# --security:仅安装标记为安全更新的包。
# -y:自动确认。
echo "[$(date)] 安装安全更新..." >> $LOG_FILE
$PKG_MGR update --security -y >> $LOG_FILE 2>&1
update_exit_code=$?
if [ $update_exit_code -eq 0 ]; then
echo "[$(date)] 安全更新安装完成。" >> $LOG_FILE
elif [ $update_exit_code -eq 1 ]; then
echo "[$(date)] 没有需要安装的安全更新。" >> $LOG_FILE
else
echo "[$(date)] 错误:更新安装失败 (退出码: $update_exit_code)。" >> $LOG_FILE
exit 1
fi
# 3. (可选) 清理缓存
$PKG_MGR clean all >> $LOG_FILE 2>&1
echo "[$(date)] 补丁安装流程结束。" >> $LOG_FILE
exit 0
注意事项:
yum update --security在较旧的 CentOS 7 上可能需要额外的插件(如yum-plugin-security)。- 在 Fedora/RHEL 8+ 中,
dnf update --security功能很完善。
适用于SUSE/openSUSE系列
#!/bin/bash
LOG_FILE="/var/log/auto-patch.log"
if [ "$(id -u)" -ne 0 ]; then
echo "错误:请以root用户运行此脚本。"
exit 1
fi
echo "[$(date)] 开始自动安装安全补丁..." >> $LOG_FILE
# 刷新源
echo "[$(date)] 刷新软件包源..." >> $LOG_FILE
zypper --non-interactive refresh >> $LOG_FILE 2>&1
# 安装补丁(安全更新)
# zypper list-patches --category security 可以列出安全补丁
# zypper patch --category security 安装安全补丁
echo "[$(date)] 安装安全补丁..." >> $LOG_FILE
zypper --non-interactive patch --category security --with-optional >> $LOG_FILE 2>&1
if [ $? -eq 0 ]; then
echo "[$(date)] 安全补丁安装完成。" >> $LOG_FILE
else
echo "[$(date)] 错误:补丁安装失败。" >> $LOG_FILE
exit 1
fi
echo "[$(date)] 补丁安装流程结束。" >> $LOG_FILE
exit 0
最佳实践与安全考虑
- 先测试(关键): 永远不要在生产环境的全部机器上直接运行未经测试的补丁脚本,先在测试环境或少量实例上运行几天。
- 处理重启: 许多内核或系统库安全补丁需要重启才能生效。
- 脚本方案: 在补丁安装后,检查哪些服务需要重启(如
needs-restarting),或检查是否安装了内核更新(/boot/vmlinuz-*),然后计划定时重启。 - 推荐工具: 使用
needrestart(Debian) 或yum-utils提供的needs-restarting命令。
- 脚本方案: 在补丁安装后,检查哪些服务需要重启(如
- 日志与通知: 务必将日志输出到文件,并考虑结合
mail命令或slack-cli发送通知。 - 锁定特定版本: 对于某些关键服务(如数据库、Web服务器),你可能不想让它自动升级大版本,可以使用
apt-mark hold <package>或yum versionlock <package>锁定版本。 - 配置管理工具: 对于大型集群,不建议使用独立Shell脚本手动管理,推荐使用 Ansible、SaltStack、Puppet 或 Kubernetes 的 Kured 等工具进行大规模、可回滚的补丁管理。
- 创建快照/备份: 在自动执行前,利用云厂商或虚拟机快照功能创建一个临时回滚点,Shell脚本可以调用云API(如
aws ec2 create-snapshot)来完成这个前置任务。
如何使用这个脚本
- 将上述代码保存为
auto_patch.sh。 - 赋予执行权限:
chmod +x auto_patch.sh。 - 手动测试:
sudo ./auto_patch.sh。 - 设置定时任务(crontab):
# 每天凌晨2点运行 0 2 * * * /path/to/auto_patch.sh