Rocky AlmaLinux 配置 dnf-automatic 安全更新
了解 Rocky Linux 9 和 AlmaLinux 9 如何配置 dnf-automatic:仅安装安全更新、启用 systemd 计时器、设置邮件提醒,并制定避免意外重启的策略。
Rocky Linux 和 AlmaLinux 上的 dnf-automatic 的作用
dnf-automatic 用于在 Rocky Linux 和 AlmaLinux 上自动安装安全更新。它是一个由 systemd 计时器启动的小型程序,会读取 /etc/dnf/automatic.conf,并应用该文件允许的更新。安装只需执行一条命令。本指南其余内容将介绍相关设置,以及这些设置如何决定它是保护服务器,还是静默地不执行任何操作。
如果您之前使用过 Debian 或 Ubuntu,那么它执行的任务与 Ubuntu VPS 上的 unattended-upgrades 相同。但有一个区别比其他区别都重要:包管理器如何定义“安全”。在 Ubuntu 上,安全更新位于单独的仓库分区中。在 RHEL 系列上,安全信息附加在已发布的公告元数据中,而这些元数据可能缺失或过时。如果将 dnf-automatic 指向没有公告数据的仓库,它会在报告成功的同时不安装任何内容。
本指南以 Rocky Linux 9 和 AlmaLinux 9 为准;截至 August 2026,这两个发行版使用 DNF 4(DNF 是 RHEL 系列使用的包管理器)。10 版本已改用 DNF5,相关名称也会变化,因此本指南将在末尾附近单独介绍。下面的每条命令都应在您自己的服务器上执行,旁边列出了预期输出。
安装 dnf-automatic 并阅读软件包附带的配置
启用自动更新应作为设置流程的一部分,放在新 VPS 的前十分钟内,并且安排在创建非 root 用户和配置防火墙之后。
sudo dnf install -y dnf-automatic
rpm -q dnf dnf-automatic
systemctl is-enabled dnf-automatic.timer全新安装后,systemctl is-enabled 会输出 disabled,因为安装软件包不会启动任何服务。这是服务器虽然“安装了 dnf-automatic”,却从未应用过任何更新的最常见原因。
DNF 版本会影响一个选项。reboot 设置在上游 DNF 4.15 中加入,Red Hat 于 2023 年 11 月通过公告 RHBA-2023:6645 将其向后移植到 dnf-4.14.0-6.el9。Rocky 9 和 AlmaLinux 9 会重新构建该软件包,因此当前系统包含此设置,而自 2023 年起未更新的系统则不包含。
配置文件是 /etc/dnf/automatic.conf。软件包附带的副本列出了此版本支持的所有选项,并注释了各自的默认值。编辑前先阅读一次,因为该文件准确反映了您的版本支持的配置。
决定行为的两个开关
download_updates 和 apply_updates 位于 [commands] 部分,用于决定行为。在 EL9(enterprise Linux 9,Rocky 9 和 AlmaLinux 9 共用的基础版本)中,二者默认都为 no。因此,启用未经修改的 dnf-automatic 后,它只会报告可用更新。
- 二者均为
no:dnf-automatic 报告可用更新,不会修改系统。 download_updates = yes和apply_updates = no:软件包会下载到 DNF 缓存。之后安装时速度更快且无需网络,但当晚不会进行安装。- 二者均为
yes和upgrade_type = default:安装所有可用更新,无论是否为安全更新。 - 二者均为
yes和upgrade_type = security:只安装安全公告中列出的软件包。
对于面向公网的 VPS,可以从以下配置开始:
[commands]
upgrade_type = security
download_updates = yes
apply_updates = yes
random_sleep = 0
network_online_timeout = 60
reboot = nevernetwork_online_timeout 表示运行在放弃前等待可用网络的秒数。这对刚启动的服务器很重要。random_sleep 是一种较旧的负载分散方式,用于在多台计算机之间错开运行时间;现在由计时器完成这项工作。运行 systemctl cat dnf-automatic.service 可查看已发布服务实际传递的确切标志。
无需等到 06:00,即可验证配置文件是否按预期工作:
sudo systemctl start dnf-automatic.service
sudo journalctl -u dnf-automatic.service -n 50 --no-pagerjournal 会显示本次运行检查了哪些内容,以及执行了哪些操作。也可以从命令行强制指定一种行为,但这只对本次运行有效,并会覆盖配置文件中的设置:
sudo dnf-automatic --downloadupdates --no-installupdatesRocky 和 Alma 中 upgrade_type = security 的真正含义
DNF 不会通过比较版本号来判断更新是否属于安全更新。它会读取勘误元数据:仓库中发布的名为 updateinfo.xml 的文件,其中每条公告都会列出修复该问题的软件包。AlmaLinux 将这些公告发布为 ALSA 公告,Rocky 将其发布为 RLSA 公告。upgrade_type = security 根据这些元数据生成过滤器,只升级与其匹配的软件包。
这会带来两个后果,而且两者都容易让人意外。
第一,没有元数据就没有更新。如果仓库不包含 updateinfo.xml,过滤器将匹配不到任何内容,本次运行会以日志中的以下内容结束:
No security updates needed, but 3 updates available系统并未完成修补,但也没有报告失败。您可以自行检查:
dnf updateinfo list --security
dnf check-update如果 dnf check-update 列出了软件包,而 dnf updateinfo list --security 完全没有输出,那么可能是没有待处理的软件包带有公告,也可能是仓库没有可供读取的公告数据。Rocky 和 AlmaLinux 都会发布这些数据,因此在这两个发行版中,空列表通常反映的是真实情况。CentOS Stream 完全不会发布这些数据。
第二,安全模式并不意味着只进行最小变更。dnf-automatic 添加安全过滤器后,仍会执行常规升级流程。因此,公告中列出的软件包会升级到仓库中的最新版本,并同时安装其依赖项。更小的变更是仅升级到修复该公告的最早版本,这需要手动运行 dnf upgrade-minimal --security。dnf-automatic 没有对应的设置项。
Rocky 还需要注意另一点。Rocky 通过自己的流程,根据 Red Hat 数据生成勘误信息,而该流程曾经滞后。2025 年 9 月,用户报告 Rocky 9 BaseOS updateinfo.xml 自 2024 年 12 月以来一直没有更新,因此 --security 缺少近期公告;Rocky 工作人员确认这是一个已知问题。如果您依赖 upgrade_type = security,应不时将公告列表与近期 RLSA 公告进行比较。对于更重视覆盖范围而非变更控制的服务器,按您选择的计划运行 upgrade_type = default 是更安全的设置。
实际运行该任务的 systemd timer
sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timerlist-timers 应显示一行,其中 NEXT 时间约在一天之后。表为空表示该 timer 未启用,因此任务不会运行。
随软件提供的 timer 会在 *-*-* 6:00 运行,并使用 RandomizedDelaySec=60m 和 Persistent=true。随机延迟会将一组服务器分散到一个小时内执行,避免所有服务器在同一秒访问镜像。Persistent=true 表示:如果机器在 06:00 处于关机状态,它会在启动后不久运行错过的任务,而不是跳过当天的执行。
使用 drop-in 修改计划。不要编辑随软件提供的 unit,因为软件包升级会替换 /usr/lib/systemd/system 下的文件。
sudo systemctl edit dnf-automatic.timer[Timer]
OnCalendar=
OnCalendar=*-*-* 03:30
RandomizedDelaySec=30m空的 OnCalendar= 行是必需的。OnCalendar 会累积设置;如果不先重置,就会保留 06:00 的条目并再添加一个条目,导致任务每天运行两次。使用 systemctl list-timers dnf-automatic.timer 确认结果,并读取 NEXT 列。相同的 drop-in 规则也适用于其他计划任务,具体内容请参阅 编写 systemd service 和 timer unit。
现在来看一个容易踩坑的地方。软件包还提供了三个 timer:dnf-automatic-notifyonly.timer、dnf-automatic-download.timer 和 dnf-automatic-install.timer。每个 timer 都会使用命令行标志启动同一个程序,而这些标志会覆盖配置文件中的 download_updates 和 apply_updates。如果在 dnf-automatic.timer 旁边启用其中一个,任务就会以两种不同的行为运行两次,看起来就像配置文件被忽略了一样。启用一个 timer,然后检查:
systemctl list-unit-files 'dnf-automatic*'如何知道某项内容何时安装?
emit_via 部分中的 [emitters] 控制报告方式。在 systemd 下,stdio 发送器会将信息写入 journal。这是最可靠的选项,因为不需要安装其他组件:
sudo journalctl -u dnf-automatic.service --since -7d --no-pagermotd 发送器会将报告写入 /etc/motd,并覆盖该文件的原有内容。如果您在那里保留登录提示信息,请不要启用此发送器。
email 发送器会连接到 email_host 的 email_port 端口,建立 SMTP(简单邮件传输协议)连接;两者默认分别为 localhost 和 25。全新的 VPS 通常没有进程监听该端口,因此连接会被拒绝,也不会发送邮件。在依赖此功能前,请运行 ss -lnt | grep ':25';如果输出为空,请配置仅用于中继的 Postfix。邮件发送正常后,主题为 Updates applied on 'web01'.,名称取自 system_name。
对于其他用途,command 发送器会将报告通过标准输入传递给您指定的程序:
[emitters]
emit_via = stdio, command
system_name = web01.example.com
send_error_messages = yes
[command]
command_format = /usr/local/bin/notify-ops
stdin_format = {body}send_error_messages 默认值为 no,这意味着运行失败时完全不会生成报告。请启用它。只报告成功结果的补丁系统还不如没有,因为这种沉默会被误认为系统正常。
dnf-automatic 不会重启服务
安装软件包会替换磁盘上的文件。已经运行的进程会继续使用内存中的旧代码,因此,对于上个月启动的守护进程,修补后的库不会立即生效。已安装状态与实际生效状态之间存在时间差,因此无人值守修补不仅需要安装策略,还需要重启策略。
sudo dnf install -y dnf-plugins-core
dnf needs-restarting -s
dnf needs-restarting -r-s 会列出其文件在启动后发生变化的 systemd 服务。-r 用于回答一个问题,并输出以下两个代码块之一:
Core libraries or services have been updated since boot-up:
* kernel
Reboot is required to fully utilize these updates.No core libraries or services have been updated since boot-up.
Reboot should not be necessary.-r 并不进行深度分析。它只检查固定的软件包列表:kernel、kernel-core、kernel-rt、glibc、linux-firmware、systemd、dbus、dbus-broker、dbus-daemon 和 microcode_ctl。如果其中某个软件包是在上次启动后安装的,就会得到第一个结果。如果系统中的其他软件也需要重启才能生效,请将其软件包名称添加到 /etc/dnf/plugins/needs-restarting.d/ 下、文件名以 .conf 结尾的文件中。
脚本需要注意:dnf needs-restarting -r 在需要重启和命令本身执行失败时都会返回非零退出状态,因此不能仅根据退出状态区分这两种情况。请读取输出文本。
重启服务的影响较小,通常也是正确的做法。重启 SSH 守护进程时,应使用已经打开的第二个 SSH 会话,以免错误配置导致无法登录。新内核则只能通过重启生效,因为正在运行的内核无法原地替换。
是否应让服务器自动重启?
[commands]
reboot = when-needed
reboot_command = shutdown -r +5 'Rebooting after applying package updates'reboot = never 是默认设置。when-changed 会在应用任何更新后重启。when-needed 仅在 needs-restarting -r 背后的检查确认替换了核心软件包时才重启。对于大多数单服务器用户,这种方式最合适,再配合自行选择的定时器时间窗口。默认的 reboot_command 会通过 shutdown 提前五分钟向已登录用户发出警告,也可以将时间延长。
启用此功能前,请先确认两点。所有依赖的服务都必须能够在启动时自动启动。手动启动的 Docker Compose 堆栈 通常会遗漏这一点。您还需要通过服务商提供的控制台或救援访问权限,因为无法启动的内核不能通过 SSH 修复。如果缺少其中任一条件,请保留 reboot = never,并在查看日志后手动重启。
Rocky、AlmaLinux 和 CentOS Stream:它们的区别
在 Rocky 9 和 AlmaLinux 9 上,上文的所有内容都完全相同,包括配置路径和单元名称。两者都会发布勘误,因此 upgrade_type = security 有可供筛选的数据。
CentOS Stream 是例外,而且差异很大。Stream 软件源不包含 updateinfo.xml,因此安全筛选条件永远无法匹配,每次运行都会报告 No security updates needed。在 Stream 上,请使用 upgrade_type = default,并接受系统会安装所有更新这一点。Stream 的版本也领先于 RHEL,因此相同设置在 Stream 主机上的更新范围会比 Rocky 或 AlmaLinux 更大。
Rocky 10 和 AlmaLinux 10 已迁移到 DNF5,相关名称也发生了变化。上游 DNF5 文档将计时器写作 dnf5-automatic.timer,将软件包自带的默认值放在 /usr/share/dnf5/dnf5-plugins/automatic.conf 中,而您的覆盖设置仍放在 /etc/dnf/automatic.conf 中;它将 download_updates 的默认值从 no 改为 yes,并将 distro-sync 添加为 upgrade_type。公告查询命令为 dnf advisory list,updateinfo 仍作为别名保留。在复制面向 9 编写的指南中的软件包名称或单元名称之前,请确认您的发行版实际安装了哪些内容:
dnf list --available '*automatic*'
systemctl list-unit-files '*automatic*'许多关于此主题的已发布指南仍只介绍 Rocky 8。这些指南编写后,可用选项已经增加,因此请检查您自己主机上的带注释配置文件,不要直接信任旧文章。
故障模式及您将看到的字符串
根本没有任何任务运行。 systemctl list-timers dnf-automatic.timer 输出空表,systemctl is-enabled dnf-automatic.timer 输出 disabled。软件包已安装,但计时器从未安装。
任务运行了,但没有安装任何内容。 journal 中包含 No security updates needed, but 3 updates available。安全过滤器未匹配到任何内容,原因可能是没有待处理的软件包带有安全公告,也可能是软件仓库未发布安全公告数据。
某个设置似乎被忽略。 DNF 会在调试级别下将未知选项记录到 automatic.conf,然后使用默认值。因此,拼写错误的键不会产生任何效果,也不会发出警告。写入 apply_update = yes,而 apply_updates 保持为 no,因此该主机会持续下载,但永远不会安装。每次修改后都运行 sudo systemctl start dnf-automatic.service,并查看 journal,不要只相信配置文件。
任务每天运行两次。 有两个计时器处于启用状态。systemctl list-unit-files 'dnf-automatic*' 可显示具体是哪两个计时器,额外的计时器还会传入优先于配置文件的选项。
没有收到邮件。 可能是没有任何程序在端口 25 上监听 email 发件器的请求,也可能是 send_error_messages 仍为 no,而唯一值得报告的事件是错误。
服务已打补丁,但仍报告旧版本。 磁盘上的文件已更新,但内存中的进程仍是旧版本。dnf needs-restarting -s 会列出需要重启的服务。
FAQ
dnf-automatic 在 Rocky Linux 上是否只安装安全更新?
只有在 upgrade_type = security 中设置了 /etc/dnf/automatic.conf,并且软件仓库发布了勘误元数据时才会如此。Rocky Linux 和 AlmaLinux 都会发布该元数据,因此过滤器可以匹配相应的公告。随附的默认值是 upgrade_type = default,安装 apply_updates = yes 后会安装所有可用更新。
为什么 dnf-automatic 报告“无需安全更新,但有 3 个更新可用”?
DNF 通过读取软件仓库中的 updateinfo.xml 来判断哪些内容属于安全更新,其中每条公告都会列出修复该问题的软件包。元数据缺失或过期时,安全过滤器不会匹配到任何内容,但普通更新仍在等待安装,因此会准确产生这行提示。CentOS Stream 完全不发布勘误信息,因此出现该提示是预期行为。在 Rocky Linux 或 AlmaLinux 上,请将 dnf updateinfo list --security 与 dnf check-update 进行比较,并确认元数据是最新的。
dnf-automatic 在更新内核后会重启服务器吗?
除非您明确要求,否则不会。reboot 选项的默认值是 never。设置 reboot = when-needed 后,只有当 dnf needs-restarting -r 背后的检查发现某个核心软件包(例如 kernel 或 glibc)在本次启动后被替换,运行任务才会重启服务器。reboot = when-changed 会在应用任意更新后重启。两者都使用 reboot_command,其默认值为 shutdown -r +5,并向已登录用户显示警告消息。
如何更改 dnf-automatic 的运行时间?
运行 sudo systemctl edit dnf-automatic.timer,并添加一个 [Timer] 部分,其中先写一行空的 OnCalendar=,再写入您的计划,例如 OnCalendar=*-*-* 03:30。这一空行是必需的,因为 OnCalendar 会累积配置;省略它会保留随附的 06:00 任务,并再添加一个任务。使用 systemctl list-timers dnf-automatic.timer 验证设置,并读取 NEXT 列。
服务器会自动安装补丁后,我还需要检查它吗?
需要。dnf-automatic 只负责安装软件包。它不会重启守护进程;除非 emit_via 指定了您实际查看的发送器,否则您不会看到任何报告。至少将 emit_via 设置为 stdio,启用 send_error_messages,以便同时报告失败情况,并在补丁维护窗口结束后运行 dnf needs-restarting -s,查找仍在运行旧代码的服务。