news 2026/10/19 1:56:56

Ubuntu 18.04服务器凌晨自动重启?彻底关闭unattended-upgrade实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 18.04服务器凌晨自动重启?彻底关闭unattended-upgrade实战指南

最近被拉去一起看一台反复在凌晨自动重启的 Ubuntu 18.04 服务器,现象很典型:凌晨三点左右机器开始刷 apt 源、下载安全补丁,如果涉及内核更新,安装完成后就自动重启。业务日志断了几分钟,批处理任务全部被打散。查了一圈,罪魁祸首就是 unattended-upgrade 这个默认开启的自动升级功能。很多人以为“关闭 unattended-upgrade”就是把某个开关改掉,实际操作下来你会发现,它背后牵着一整条 apt 定时器、systemd 服务、debconf 配置和包依赖链,哪一层没照顾到,它都有可能换个入口再跑起来。

这篇文章就围绕 18.04 环境,讲清楚 unattended-upgrade 的完整关闭思路:先说它到底是怎么被调起来的,再给三种不同力度的关闭方式,然后是关闭后的验证手段,最后会聊几个“别一刀切”的折中方案和常见翻车恢复流程。不管你是只想让服务器别自动重启,还是想把自动升级彻底赶出生产环境,这篇都能直接照着操作。

1. 先认清 unattended-upgrade 的运作链路,才知道要关掉谁

1.1 自动更新不是“一个脚本在跑”,而是配置、服务、定时器三层协作

在 Ubuntu 18.04 上,unattended-upgrade 这个功能至少横跨三层。

第一层是 apt 配置文件,最核心的是/etc/apt/apt.conf.d/20auto-upgrades。这个文件里的APT::Periodic::Unattended-Upgrade变量就是总开关,置为"1"表示允许无人值守升级,置为"0"表示禁止。旁边还有Update-Package-Lists、Download-Upgradeable-Packages等变量,分别控制“自动刷新软件源列表”和“自动下载可升级包”。

第二层是 systemd 服务和定时器。18.04 上常见的有apt-daily.service、apt-daily-upgrade.service,以及配套的apt-daily.timer、apt-daily-upgrade.timer。定时器到点后拉起服务,服务再去执行 apt 的相关脚本。apt-daily-upgrade.timer负责的就是真正执行升级动作的路径,它会调用/usr/bin/unattended-upgrade。有的带桌面环境的发行版还会额外有unattended-upgrades.service和unattended-upgrades.timer这两兄弟,用途一样,也是定时触发自动升级。

第三层是unattended-upgrade这个 Python 脚本本身。它读取/etc/apt/apt.conf.d/50unattended-upgrades中的策略,判断哪些更新来源允许自动安装,哪些包要放进黑名单,安装完成后如果发现系统处于“需要重启”状态,还会根据配置决定要不要自动重启。

这三层是联动的:只有配置文件里开着自动升级,定时器就算触发了也只是空跑;反过来,如果只把配置文件里的开关改成"0",但没处理定时器,以后有人把配置文件再改回来,自动升级会立刻恢复。这就是为什么“关闭 unattended-upgrade”经常出现“关了跟没关一样”的情况。

1.2 哪些环境真正需要关闭它,哪些环境其实不该关

我见过不少对自动升级深恶痛绝的维护者,但说实话,不是所有机器都应该关。

如果是一台跑着面向用户业务、又没人实时盯的服务器,自动升级带来的不确定风险往往大于收益。最典型的就是凌晨自动重启:内核一更新,unattended-upgrade检测到/var/run/reboot-required标记,就会按照配置直接重启机器。对跑了长任务、批处理、数据库、消息队列这类服务的机器来说,一次没人预期的重启可能是灾难。

第二个典型场景是多节点集群。节点都从同一个镜像模板拉起,理想状态下所有节点软件版本一致。如果让每个节点各自自动更新,几个月后再看,各节点内核版本、动态库版本可能已经五花八门,排查问题的时候非常痛苦。对这种环境,我更建议把更新变成可控的发布流程,而不是放任每台机器自行漂移。

第三种是合规要求比较严格的环境。内部变更流程可能要求“任何软件变更必须经过审批窗口”,自动更新相当于绕过了审批,这在审计复盘时是说不清道不明的事项。

反过来,个人开发机、测试环境、没有专职维护的小型 VPS,我反而建议保留自动安全更新。毕竟 18.04 这类系统已经过了大版本支持期,安全补丁的及时性比什么都重要,手动维护一旦忘了,风险更不可控。

2. 实操:配置层、服务层、包层三种关闭方式怎么组合

2.1 最直接的配置层关闭:把 20auto-upgrades 里的开关翻成 0

先看当前配置文件长什么样:

cat /etc/apt/apt.conf.d/20auto-upgrades

正常情况下你会看到类似这样的内容:

APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "0"; APT::Periodic::Unattended-Upgrade "1";

要关闭无人值守升级,核心是把Unattended-Upgrade改成"0":

APT::Periodic::Update-Package-Lists "0"; APT::Periodic::Download-Upgradeable-Packages "0"; APT::Periodic::AutocleanInterval "0"; APT::Periodic::Unattended-Upgrade "0";

这里有个容易被忽略的细节:Update-Package-Lists是不是也要改成"0",取决于你的诉求。如果你只是不想让系统自动安装软件包,但希望它每天自动刷新软件源索引,那可以让Update-Package-Lists保持"1"。刷新索引占用资源很小,也能避免以后手动执行apt update时发现源列表已经过期很久。如果你要的是“这台机器除了我手动操作之外,apt 什么都不能自动做”,那四个变量全部清零。

提示:apt 配置文件是“后读取覆盖先读取”的机制,如果你在/etc/apt/apt.conf.d/下还有其他文件也想设置同名变量,最终生效值以数字排序靠后的文件为准。所以别只盯 20auto-upgrades,排查时还要看同目录下其他文件。

2.2 用 dpkg-reconfigure 快速生成标准配置

除了手工编辑文件,还有一条更省事的命令:

sudo dpkg-reconfigure unattended-upgrades

执行后会弹出交互界面,核心问题就是“是否自动下载并安装稳定更新”。选择“No”,系统会自动把 20auto-upgrades 里的Update-Package-Lists和Unattended-Upgrade都写成"0"。

但我必须提醒你,这个命令是把双刃剑。它生成的是“完全关闭”的标准模板,不会帮你保留“只刷新索引、不自动安装”的中间状态。如果你有中间态需求,最后还是得手动去编辑 20auto-upgrades。

另外,如果你的环境里没有这个包或者 dpkg 数据库状态异常,dpkg-reconfigure unattended-upgrades可能会提示找不到可配置的包,这时就走手工编辑那一步更可靠。

2.3 服务层兜底:停掉并禁用定时器,防止“卷土重来”

配置层做了之后,强烈建议再处理服务层。因为在某些系统里,即使配置文件已经不允许自动升级,相关的 systemd 定时器依旧会周期性触发,只是脚本内部判断后立即退出。如果哪天配置文件被桌面端更新工具或人为误操作改回去,定时器又会立刻恢复自动升级。

在 18.04 上,最常见的相关单元有这些:

sudo systemctl stop unattended-upgrades.service sudo systemctl disable unattended-upgrades.service sudo systemctl stop unattended-upgrades.timer sudo systemctl disable unattended-upgrades.timer sudo systemctl stop apt-daily-upgrade.timer sudo systemctl disable apt-daily-upgrade.timer

注意:执行到不存在的单元时,systemctl 会报Unit xxx could not be found。这是正常的,说明你的系统没启用这个单元,直接忽略并继续处理其他的就行。apt-daily-upgrade.timer在大多数服务器版 18.04 上是真实存在的,它就是自动安全更新背后最常见的定时触发器,这一条不能漏。

如果希望绝对稳妥,还可以把对应服务 mask 掉:

sudo systemctl mask unattended-upgrades.service sudo systemctl mask apt-daily-upgrade.service

mask比disable更狠,disable只是取消开机启动,mask是把单元软链接到/dev/null,任何服务想拉起它都会被系统拒绝。这个操作适合对稳定性要求极高的生产机。恢复的时候要记得unmask。

2.4 包层处理:卸载 unattended-upgrades 是不是最彻底的做法

如果前面的操作你都嫌麻烦,也可以直接卸载:

sudo apt remove unattended-upgrades

或者连配置文件一起清干净:

sudo apt purge unattended-upgrades

卸载之后,20auto-upgrades 文件不一定被删除,但Unattended-Upgrade "1"这种设置通常会随包被移除。问题是,有些发行版元包会把unattended-upgrades作为依赖带上,比如某些服务器环境的最小化安装集合。一旦你之后执行了apt install ubuntu-minimal之类的操作,或者运行某些会重置依赖关系的系统整理工具,它很可能又被拉回来。

所以我的建议是:卸载不是终点,卸载后仍要检查配置层和服务层。更常见的做法是“修改配置 + 禁用定时器 + 不依赖卸载”,这样既保留包,又不触发自动升级。万一以后想恢复自动安全更新,重新开启的时间成本也最低。

下面用一个表格把这几种方式的关键差异列出来,方便你在不同场景下选型:

关闭方式作用层级最适配场景需要注意的副作用
修改 20auto-upgrades配置控制永久关闭,不需要保留自动刷新索引如果只改这里,后续配置文件被改写则可能恢复
dpkg-reconfigure配置生成快速批量操作,不想接触文本编辑器会同时关闭自动刷新索引,中间状态需手动改回
停用/禁用 systemd 单元服务调度防止定时器触发空跑或意外恢复disable不阻止其他依赖拉起服务,必要时配合mask
卸载/清除包包管理已确认不需要任何无人值守升级能力可能被元包依赖重新拉回,需要复查

3. 关闭之后怎么验证,不留“已关闭”的错觉

3.1 用 systemctl 确认定时器状态

关闭操作做完后,先查 systemd 层面:

systemctl list-timers --all | grep -E 'apt|unattended'

如果之前禁用了apt-daily-upgrade.timer和unattended-upgrades.timer,输出里应该看不到它们,或者即使列出,名字前面也不会是可执行状态。再逐个确认服务状态:

systemctl is-enabled unattended-upgrades.service systemctl is-active unattended-upgrades.service

is-enabled返回disabled或masked,is-active返回inactive,基本可以确定服务层已经关死。如果is-active还显示active,说明服务正在运行,你可以继续追查是哪个定时器把它拉起来的。

3.2 用 apt-config 验证真实生效值

配置层到底生效没有,必须看 apt 实际读取到的值,而不是只看文件里的文本。因为可能存在多个 apt.conf.d 文件互相覆盖,文件里写的和实际生效的值可能不一致。用下面命令直接看运行时配置:

apt-config dump | grep -E 'Unattended-Upgrade|Update-Package-Lists|Download-Upgradeable'

重点看APT::Periodic::Unattended-Upgrade的最终值是不是"0"。同时也看一下Update-Package-Lists最终值是否符合预期。

再配合检查文件内容:

cat /etc/apt/apt.conf.d/20auto-upgrades grep -R "Unattended-Upgrade" /etc/apt/apt.conf.d/

后者能帮你找出是否有其他文件也定义了该变量,避免出现某个文件把值覆盖回"1"的情况。

3.3 观察日志和进程,确认没有任何残留行为

关闭不是一瞬间完成的,如果关闭时正好有自动升级在跑,可能会有残留的 dpkg 进程或锁文件。验证一下:

pgrep -af unattended-upgrade pgrep -af 'apt.systemd.daily' ls -lt /var/log/unattended-upgrades/

正常情况下,pgrep没有输出。日志目录如果存在,观察最新日志文件的修改时间,如果已经停在关闭操作之前的日期,说明之后没有新的自动升级会话。如果你不放心,还可以看 systemd 日志:

journalctl -u unattended-upgrades.service --since "1 hour ago" journalctl -u apt-daily-upgrade.service --since "1 hour ago"

没有新记录就是干净状态。

提示:我遇到过一种“关了但没完全关”的情况,配置文件和服务都处理好了,结果系统里还残留着/etc/cron.daily/apt-compat定时任务,它会周期性执行 apt 脚本。虽然最终脚本也会读取配置变量并返回,但排查时你会在日志里看到 apt 活动,导致误判。处理掉服务层和配置层之后,这类 cron 残留一般不足为惧,但如果你的环境对“apt 完全不可自动运行”有严格要求,也要把它纳入检查范围。

4. 不想彻底关掉?只关自动重启、只排除内核更新也足够

4.1 需求一:保留安全补丁,但禁止自动重启

很多人真正讨厌的不是自动升级,而是自动重启。如果你愿意让系统安装安全补丁,只是不想在凌晨被毫无征兆地重启打断,可以在/etc/apt/apt.conf.d/50unattended-upgrades里找到并修改这两项:

Unattended-Upgrade::Automatic-Reboot "false"; Unattended-Upgrade::Automatic-Reboot-Time "02:00";

Automatic-Reboot设为"false",意思就是无论升级后是否需要重启,都不主动重启机器。重启动作留给你自己来决定,你可以在业务低峰期统一重启,或者等下一次计划维护窗口一并处理。

需要说明的是,Automatic-Reboot-Time是给“允许自动重启”的情况用的,比如你希望它在凌晨四点重启,就把时间写成"04:00"。一旦你把Automatic-Reboot设成了"false",时间这项存不存在都无所谓。这种配置适合那种“可以打补丁,但绝不能擅自重启”的数据库节点、缓存节点、长任务执行机。

4.2 需求二:升级普通软件包,但把内核更新排除在外

还有一种常见诉求:普通软件包随便升,内核更新坚决不动。这样做的主要动机是,内核升级后通常要求重启,而且内核变更对线上行为的影响比普通包大得多。

修改/etc/apt/apt.conf.d/50unattended-upgrades,找到Package-Blacklist部分,把内核相关包写进黑名单:

Unattended-Upgrade::Package-Blacklist { "linux-image-.*"; "linux-generic"; "linux-headers-.*"; };

linux-image-.*匹配所有内核镜像包,linux-generic是元包,直接锁掉可以防止它把新内核镜像带进来。这样系统每天依然会安装其他安全更新,但不会自动升级内核。

我必须提醒一句:这个方案的代价是内核安全隐患需要你手动处理。如果你所在团队的运维能力不足,或者长期没人维护,我宁可你保留自动内核升级,至少安全上不裸奔。排除内核更新只适合那种“有固定内核版本要求、有专门安全负责人”的环境。

4.3 需求三:自动升级关掉后,手动维护应该形成什么习惯

关闭自动升级之后,很多人会陷入另一个极端:彻底忘了更新这回事。三个月后再去apt update,会发现源列表里的仓库签名过期、依赖解析出问题,升级成本远比按时更新高得多。

我建议形成固定的手动维护节奏。最基础的命令组合是这样:

sudo apt update apt list --upgradable

然后根据升级清单决定是否执行:

sudo apt upgrade --with-new-pkgs

--with-new-pkgs这个参数在 18.04 上比较关键,它允许 apt 在升级过程中把新依赖的软件包一并安装,避免出现“为了升级 A,必须新装 B,但 apt 默认不愿装新包”的尴尬。开启无人值守升级时系统内部也是类似逻辑,手动维护时别漏了它。

升级完成后检查是否需要重启:

test -f /var/run/reboot-required && echo "reboot required" cat /var/run/reboot-required.pkgs 2>/dev/null

如果需要重启,在业务低峰期挑个时间统一重启,再通过uptime和服务状态确认恢复。习惯了这套节奏之后,你完全可以用脚本或定期任务把“固定维护窗口 + 手动升级”自动化,效果比无人值守升级更可控。

5. 翻车现场与恢复指南:从“又自动升级了”到“重新开启默认策略”

5.1 翻车现场:只改了配置没动服务,或者反过来

最常见的翻车,就是只处理了一侧。有人说“我明明把 20auto-upgrades 里的开关改成 0 了,为什么还自动升级?”大概率是没注意到系统里还有另一个配置文件或者其他触发路径。有人说“我明明把服务停了,怎么还会更新?”多半是因为 apt 配置文件里的开关还开着,定时器被其他依赖重新拉起后又开始干活。

我在实际环境中的处理顺序永远是:先看配置,再停服务,最后再看日志。配置是自动升级的“油门”,服务是“发动机”,两个都踩住才叫停车。只松开其中一个,它总有一天会自己跑起来。

5.2 翻车现场:桌面端软件更新器把配置改回“1”

如果你在带桌面环境的 18.04 上操作,还有一个隐蔽的重灾区:桌面的“软件更新器”设置。在里面把“自动更新”改成“仅下载更新”或“立即安装”,系统会悄悄把 20auto-upgrades 里的变量改写。有时候你前一天刚改成"0",第二天 someone 打开软件更新器点了一下“检查更新”,配置又被写回"1"。

对于服务器环境,解决办法是绕开桌面端,直接用命令行维护。对于桌面环境,我建议在关闭自动升级后,顺便把软件更新器的相关设置固定成“从不检查更新”,减少误触发的可能。

5.3 翻车现场:关闭时撞上 apt 锁,折腾了半天发现升级还没停干净

关闭操作如果在自动升级正在运行的时候进行,可能会撞上 dpkg 的锁。症状就是执行apt命令时报:

Could not get lock /var/lib/dpkg/lock-frontend

这时候不要强行 kill,也不要直接删锁文件,那是最后的手段。先停掉相关服务,让正在跑的脚本正常退出:

sudo systemctl stop apt-daily-upgrade.service sudo systemctl stop apt-daily.service

再检查有没有残留的升级进程:

pgrep -af 'unattended-upgrade|apt.systemd.daily'

如果有,给脚本一点时间,或者选择在确认业务影响可控的情况下再处理。等锁释放后,重新执行验证步骤。

5.4 恢复指南:怎么把自动升级重新接回来

有些环境是“先关一阵子,等版本稳定了再打开”。恢复时不要只改配置文件,要系统地反向操作:

sudo dpkg-reconfigure unattended-upgrades

交互里选择“Yes”,dpkg 会重新生成允许自动更新的配置。然后恢复定时器:

sudo systemctl unmask unattended-upgrades.service sudo systemctl enable --now unattended-upgrades.timer sudo systemctl enable --now apt-daily-upgrade.timer

如果之前没有卸载包,恢复就非常简单。如果卸载了包,那就先重新安装:

sudo apt install unattended-upgrades

装完后 20auto-upgrades 通常会自动生成,再用apt-config dump确认变量已经变成"1"。最后看一眼日志,确认下一次定时器触发时能正常写入新的升级记录,这样才算真正恢复。


我在实际环境里最喜欢用的关闭方案,概括起来就是一句话:配置文件清零、定时器禁用、日志留底。不需要把包卸载掉,也不要只改一半。这样既满足“不让机器随便动”的诉求,也保留将来一键恢复的余地。如果你也是被凌晨自动重启折腾到头大的人,不妨照着这个链路走一遍,确认完三层状态之后,那台 18.04 才能真正睡个安稳觉。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 22:07:01

嵌入式开发必学数据结构:线性表、顺序表与链表实战指南

做嵌入式开发的人,十有八九都经历过这种场面:串口数据一多,缓冲区就不够用了;用数组存设备节点状态,增删一个设备要把整个表重新排一遍;中断里想往等待队列里塞数据,写着写着就不知道指针飘到哪…

作者头像 李华
网站建设 2026/10/17 23:41:04

麒麟V10救援模式显示异常排查与修复指南

我去年底接手过一台启动黑屏的麒麟V10-SP1机器,当时第一个判断就是救援模式,等真正进到救援模式,才发现显卡驱动加载那段的显示问题比系统本身的故障还麻烦。这篇文章就结合麒麟桌面系统V10-SP1 2503这个版本,把救援模式下显示异常…

作者头像 李华
网站建设 2026/10/18 8:26:41

百万级并发网络编程:Reactor模型原理与epoll实战调优

搞 Linux 网络编程的人,早晚都会撞上“百万级并发”这个词。面试要聊、压测要跑、真正的线上流量高峰也在考人。我早年在某内部系统上做长连接服务,一开始很天真,一个连接开一个线程,数据量稍微上来,整个进程直接卡到没…

作者头像 李华
网站建设 2026/10/17 21:38:28

从阻塞IO到epoll:高并发网络编程核心机制与实战避坑指南

你刷着手机里的短视频,或者发出一条朋友圈,背后的服务器可能在同一瞬间接收了成千上万条连接请求。很多人用着Netty、Redis或者Nginx,知道它们“性能好、并发高”,但问到底层怎么做到的,多半会卡在“Linux网络IO模型”…

作者头像 李华
网站建设 2026/10/18 4:15:09

GoLand单文件执行全攻略:包模型、Run配置与排坑指南

如果你刚用GoLand,十有八九遇到过这个场景:写了一个十来行的Go小文件,想在编辑器里右键直接跑起来,结果菜单里死活找不到Run,或者好不容易点了Run,Console里刷出一片编译器错误,你盯着undefined…

作者头像 李华
网站建设 2026/10/17 11:32:49

双绞线制作与测试全流程:从线序标准到故障排查

开始之前,先弄明白这个实验为什么值得认真做每次带新生做第一个网络实验,我都要先强调一句:双绞线制作与测试,看着简单,却是整个计算机网络课程里"性价比"最高的一个实验。为什么这么说?因为后面…

作者头像 李华