SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-09-04

Rocky AlmaLinux 如何配置 dnf-automatic 安全更新

了解 Rocky Linux 9 和 AlmaLinux 9 上 dnf-automatic 的安全更新配置,包括仅安装安全补丁、systemd 计时器、邮件提醒和避免意外重启的策略;DNF5 版本另有说明。

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 为准。这些系统使用 DNF 4(DNF 是 RHEL 系列使用的软件包管理器),内容截至 2026 年 8 月。10 版本已改用 DNF5,相关名称也有所变化,因此本指南会在接近末尾的位置单独介绍它们。下面的每条命令都应在您自己的服务器上运行,旁边列出了预期输出。

安装 dnf-automatic 并阅读随附配置

启用自动更新应作为其他初始化步骤的一部分,放在新 VPS 上的前 10 分钟内,并且应在创建非 root 用户和配置防火墙之后完成。如果防火墙尚未配置,Rocky 和 AlmaLinux 随附的是 firewalld。使用几条命令即可开放 SSH、开放网站监听的端口,并使这些设置在重启后仍然有效。

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 = never

network_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-pager

日志会显示本次任务检查了什么,以及执行了什么操作。也可以从命令行强制指定一种行为,但该设置只对本次运行覆盖配置文件:

sudo dnf-automatic --downloadupdates --no-installupdates

Rocky 和 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.timer

list-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-pager

motd 发送器会将报告写入 /etc/motd,并替换该文件的现有内容。如果您在那里保留登录提示语,请不要启用此发送器。

email 发送器会在 email_port 上连接到 email_host 的 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 daemon,这样即使配置错误,也不会把您锁在系统之外。新内核属于只能通过重启解决的情况,因为正在运行的内核无法原地替换。如果您希望将某天早上的更新分为这两类,哪些更新需要重启,哪些更新只需要重启服务 会逐个软件包检查输出。

容器属于另一种情况,因为 dnf-automatic 只更新主机的软件包,不会修改镜像中预置的用户空间。因此,运行 Rocky Linux 或 AlmaLinux 上的 Docker Engine 的服务器还需要重新拉取镜像并重新创建容器,修复才会应用到实际提供网络流量的代码。

是否应自动重启服务器?

[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 有可供筛选的数据。前文介绍的 Rocky 过期勘误,是它们在日常使用中的少数实际差异之一。因此,如果服务器尚未部署,请将这一点与区分两者的兼容性承诺和旧 CPU 支持一并权衡。

CentOS Stream 是例外,而且差异很明显。Stream 软件源不包含 updateinfo.xml,因此安全筛选条件永远无法匹配,每次运行都会报告 No security updates needed。在 Stream 上,请使用 upgrade_type = default,并接受安装所有更新。Stream 的版本也领先于 RHEL,因此在 Stream 服务器上,该设置的变动会比 Rocky 或 AlmaLinux 上的同一设置更多。这并非打包方式偶然造成的差异,而是 Red Hat 在 2020 年决定将 CentOS 转变为 RHEL 滚动预览版的结果;正是这一决定促成了 Rocky Linux 和 AlmaLinux 的诞生。

Rocky 10 和 AlmaLinux 10 已迁移到 DNF5,因此相关名称发生了变化。上游 DNF5 文档将计时器列为 dnf5-automatic.timer,将系统提供的默认值放在 /usr/share/dnf5/dnf5-plugins/automatic.conf 中,而您的覆盖配置仍放在 /etc/dnf/automatic.conf 中;它将 download_updates 的默认值设为 yes,而不是 no,并新增 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。软件包已安装,但计时器从未安装。

任务运行了,但没有安装任何内容。 日志中包含 No security updates needed, but 3 updates available。安全筛选器没有匹配到任何内容,原因可能是没有任何待处理更新带有安全公告,也可能是软件仓库不提供公告数据。

某个设置似乎未生效。 DNF 会在调试级别将未知选项记录到 automatic.conf,然后使用默认值。因此,拼写错误的键不会产生任何变化,也不会发出警告。设置 apply_update = yes,但 apply_updates 仍保持为 no,结果系统会持续下载,却从不安装。每次编辑后,运行 sudo systemctl start dnf-automatic.service 并查看日志,不要仅凭配置文件判断。

任务每天运行两次。 有两个计时器已启用。systemctl list-unit-files 'dnf-automatic*' 会显示具体是哪两个,额外的计时器还会传入覆盖配置文件的参数。

没有收到邮件。 可能是 email 发件器使用的 25 端口没有进程监听,也可能是 send_error_messages 仍为 no,而唯一值得报告的内容只是错误。

服务已应用补丁,但仍报告旧版本。 磁盘上的文件已更新,但内存中的进程仍在运行旧版本。dnf needs-restarting -s 会列出需要重启的服务。

FAQ

dnf-automatic 在 Rocky Linux 上是否只安装安全更新?

只有在 upgrade_type = security 中设置了 /etc/dnf/automatic.conf,并且软件仓库发布了 errata 元数据时才会如此。Rocky Linux 和 AlmaLinux 都会发布这些元数据,因此过滤器可以根据公告进行匹配。随附的默认值是 upgrade_type = default,在 apply_updates = yes 后会安装所有可用更新。

为什么 dnf-automatic 报告“无需安全更新,但有 3 个更新可用”?

DNF 通过读取软件仓库中的 updateinfo.xml 来判断哪些更新属于安全更新。每条公告都会列出修复该问题的软件包。当这些元数据缺失或过期时,安全过滤器匹配不到任何内容,但普通更新仍在等待安装,因此会准确显示该行。在完全不发布 errata 的 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,查找仍在运行旧代码的服务。