Ubuntu(16.04/18.04) 默认会每天自动安装系统的安全更新,但是不会自动安装包的更新。本文梳理 Ubuntu 16.04/18.04 系统的自动更新机制,并介绍如何配置系统自动更新所有的包。说明:简单起见,本文中使用 Ubuntu 指代 Ubuntu 16.04/18.04。

系统需要更新

当我们远程登录系统时,会收到如下图所示的更新相关的消息:

红框中的第一行文字说明系统中有 149 个包需要更新。第二行说明没有安全相关的包需要更新。之所以会这样,是因为 Ubuntu 默认的配置会每天自动安装安全更新而忽略其它包的更新。接下来我们就介绍 Ubuntu 中的自动更新机制。

通过定时任务执行更新

Ubuntu 默认定义了 4 个 systemd unit 执行更新任务,它们分别是:

/lib/systemd/system/apt-daily-upgrade.service
/lib/systemd/system/apt-daily-upgrade.timer
/lib/systemd/system/apt-daily.service
/lib/systemd/system/apt-daily.timer

其中的 apt-daily.timer 和 apt-daily-upgrade.timer 是两个触发器,分别在每天指定的时间触发 apt-daily.service 和 apt-daily-upgrade.service。这两个 service 的类型都是 oneshot,意思是当任务完成后 service 进程退出。这两个 service 其实调用的是同一个脚本: /usr/lib/apt/apt.systemd.daily。 apt-daily.service 为脚本传入参数 "update",其功能为检查系统的更新并下载对应的更新包。apt-daily-upgrade.service 为脚本传入参数 "install",其功能为安装更新并删除缓存在本地的更新包。

apt-daily.timer 默认每天触发两次,分别为 6 点和 18 点,主要是为了缓解服务器端的下载压力。我们可以根据自身业务的特点设置合适的触发时间。
apt-daily-upgrade.service 默认每天在 6 点触发一次,我们也可以设置为其它时间,比如午夜。

apt.systemd.daily 脚本

/usr/lib/apt/apt.systemd.daily 脚本负责完成与更新相关的一系列工作,这些工作主要分为两大块:

  • 检查更新并下载更新包
  • 安装更新并清理更新包

apt.systemd.daily 脚本中调用 apt-config 命令从 /etc/apt/apt.conf.d/10periodic 文件和 /etc/apt/apt.conf.d/20auto-upgrades 读中取配变量,并根据这些变量的值来控制系统的更新策略。下面我们介绍几个比较重要的配置项。

隔多少天执行一次 apt-get update,默认是 1 天,0 表示不执行该操作:

APT::Periodic::Update-Package-Lists "";

隔多少天执行一次 apt-get upgrade --download-only 下载更新包,0 表示不执行该操作:

APT::Periodic::Download-Upgradeable-Packages "";

下载的更新版被缓存在目录 /var/cache/apt/archives/ 中,执行升级操作时直接从缓存目录中读取包文件而不是从网络上下载。

隔多少天执行一次 apt-get autoclean 清除无用的更新包,0 表示不执行该操作:

APT::Periodic::AutocleanInterval "";

隔多少天执行一次 Unattended-Upgrade 执行系统安全更新(或者所以包的更新),0 表示不执行该操作:

APT::Periodic::Unattended-Upgrade "";

通过这些配置,我们可以控制自动更新的频率和行为。注意,到目前为止的配置还只能安装系统的安全更新,如果要想安装所有包的更新还需要其它的配置,相关内容我们在后面的小节中介绍。

在继续介绍后面的内容前,让我们先来了解一下 apt.systemd.daily 脚本中用到的 apt-config 命令和 apt.systemd.daily 脚本依赖的配置文件。

apt-config 命令
apt-config 是一个被 APT 套件使用的内部命令,使用它可以在脚本中提取 /etc/apt/apt.conf 目录下配置文件中的信息。
比如,如果要在脚本中获取 APT::Periodic::Update-Package-Lists 的设置,可以使用下面的代码:

#!/bin/bash
ABC=
eval $(apt-config shell ABC APT::Periodic::Update-Package-Lists)
echo ${ABC}

此时脚本变量 ABC 中保存的就是 APT::Periodic::Update-Package-Lists 的值。

10periodic 和 20auto-upgrades
/etc/apt/apt.conf.d/10periodic 是 update-notifier-common 的配置文件:

$ dpkg-query -S /etc/apt/apt.conf.d/10periodic
update-notifier-common: /etc/apt/apt.conf.d/10periodic

在 ubuntu 16.04 和 18.04 中,这两个文件的默认内容是一样的。apt.systemd.daily 脚本在注释中说我们可以通过 /etc/apt/apt.conf.d/10periodic 文件自定义相关的变量值,它通过 get-config 命令来获得这些变量的值。但是测试的结果是 /etc/apt/apt.conf.d/20auto-upgrades 文件中的变量会覆盖 /etc/apt/apt.conf.d/10periodic 文件中的变量。看来是 get-config 命令根据文件名称的顺序,排在后面的文件中的变量会覆盖前面文件中的变量。
在 desktop 版本中,通过 GUI 程序修改相关的变量,这两个文件都会被修改并保持一致,所以在 server 版中我们最好也同时修改这两个文件并保持其内容一致。

unattended-upgrades

Ubuntu 实际上是通过 unattended-upgrades 命令来自动安装更新的。Ubuntu 16.04/18.04 默认安装了这个包,如果碰到没有安装的情况你还可以通过下面的命令自行安装:

$ sudo apt install unattended-upgrades

unattended-upgrades 的配置文件为 /etc/apt/apt.conf.d/50unattended-upgrades
注意,unattended-upgrades 不仅能够安装系统的安全更新,还可以安装所有包的更新。但是默认的配置只安装安全更新,我们可以通过配置项让 unattended-upgrades 安装所有的包更新或者只安装安全更新。

unattended-upgrades 命令被设计为通过 cron 定时执行系统更新,但在 Ubuntu 16.04/18.04 中是通过 systemd 的 timer unit 定时触发 service unit 执行的。
unattended-upgrades 命令的日志文件存放在 /var/log/unattended-upgrades 目录下。

unattended-upgrade 命令常见的用法之一是检查系统是否有更新:

$ sudo unattended-upgrade --dry-run

另一种用法是安装更新:

$ sudo unattended-upgrade

在 apt.systemd.daily 脚本中执行 unattended-upgrade 命令时,由于更新包已经提前下载到缓存目录了(/var/cache/apt/archives),所以直接它直接使用缓存中的更新包。

配置文件 50unattended-upgrades
50unattended-upgrades 文件中的默认配置只是安装安全更新:

Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESM:${distro_codename}";
// "${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";
};

如果要自动安装所有包的更新,只要取消下面行的注释就行了:
"${distro_id}:${distro_codename}-updates";

我们还可以通过黑名单的方式指定不更新哪些包:

Unattended-Upgrade::Package-Blacklist {
"vim";
"libc6";
"libc6-dev";
"libc6-i686";
};

下面的配置项指定在更新后移除无用的包:

Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";

有些更新需要重启系统,而默认的配置是不重启系统的。下面的配置允许重启系统(更新完成后,如果需要重启,立即重启系统):

Unattended-Upgrade::Automatic-Reboot "true";

但是多数情况下我们更期望指定一个时间让系统重启(如果需要重启,在下面配置中指定的时间重启系统):

Unattended-Upgrade::Automatic-Reboot-Time "02:38";

在系统更新的过程中发生了错误怎么办?当然是通知管理员啦!下面的配置在发生错误时给管理员发送邮件:

Unattended-Upgrade::Mail "user@example.com";
Unattended-Upgrade::MailOnlyOnError "true";

注意:如果要向外网发送邮件,需要安装 mailx 等工具。

关闭自动更新

如果你的主机运行在封闭的环境中,并且无法连接到有效的更新源,此时可以选择关闭自动更新功能。首选的方法是停止相关的服务:

$ sudo systemctl stop apt-daily.service
$ sudo systemctl stop apt-daily.timer
$ sudo systemctl stop apt-daily-upgrade.service
$ sudo systemctl stop apt-daily-upgrade.timer
$ sudo systemctl disable apt-daily.service
$ sudo systemctl disable apt-daily.timer
$ sudo systemctl disable apt-daily-upgrade.service
$ sudo systemctl disable apt-daily-upgrade.timer

或者修改自动更新程序的配置文件也可以,同时更新 /etc/apt/apt.conf.d/10periodic 和 /etc/apt/apt.conf.d/20auto-upgrades:

APT::Periodic::Update-Package-Lists "";
APT::Periodic::Unattended-Upgrade "";

改为

APT::Periodic::Update-Package-Lists "";
APT::Periodic::Unattended-Upgrade "";

故障调查

因为 apt.systemd.daily 脚本同时调用了 apt-get 和 unattended-upgrade 等命令,所以相关的日志也分散在不同的地方。apt-get 相关的日志在 /var/log/apt 目录下,unattended-upgrade 命令的日志在 /var/log/unattended-upgrades 目录下。

参考:
unattended-upgrade man page
Automatic Updates
AutomaticSecurityUpdates
apt-config man page
如何在Ubuntu 16.04上安装自动安全更新
How to set up automatic updates on Ubuntu Server 18.04
Ubuntu Enable Automatic Updates Unattended Upgrades
Ubuntu 16.04: Auto apt update and apt upgrade
mvo5/unattended-upgrades

Ubuntu Server : 自动更新的更多相关文章

  1. ubuntu关闭自动更新、打开 ubuntu 的 apport 崩溃检测报告功能

    菜单栏点 系统 --->首选项 --->启动应用程序 --->更新提示 前面的钩打掉 关闭即可     =========== 打开 ubuntu 的 apport 崩溃检测报告功能 ...

  2. 在ubuntu server中安装和配置docker

    经过一段时间针对不同版本的学习,现在总结当前最新的安装配置过程(应该也是比较简单的) 如果不清楚什么是docker,请参考 https://www.docker.com/ 准备工作 建议在安装之前运行 ...

  3. ubuntu Server 14 自动更新

    https://help.ubuntu.com/stable/serverguide/automatic-updates.html http://spin.atomicobject.com/2014/ ...

  4. 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新

    源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...

  5. ubuntu server设置时区和更新时间

    ubuntu server设置时区和更新时间 今天测试时,发现时间不对,查了一下时区: data -R    结果时区是:+0000 我需要的是东八区,这儿显示不是,所以需要设置一个时区   一.运行 ...

  6. [转]ubuntu server:开机自动登录

    原文链接: Ed29.com http://ed29.com/ubuntu%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95 ...

  7. Ubuntu Server安装图形界面全过程

    转载自:http://blog.csdn.net/sunbaigui/article/details/6624110, http://mikewolfli.blog.163.com/blog/stat ...

  8. vagrant Ubuntu server 12.04 dpkg: dependency problems prevent configuration of python-gi

    Ubuntu server 12.04因为尝试安装过xfce,导致sudo apt-get install xxx 都会返回,如: vagrant@precise32:~$ sudo apt-get ...

  9. Ubuntu Server 12.04安装图解教程

                                                                                                Ubuntu S ...

随机推荐

  1. J2EE:Servlet上传文件到服务器,并相应显示

    Servlet 可以与HTML一起使用来允许用户上传文件到服务器 编辑上传文件的页面upload.html 注意事项:上传方式使用POST不能使用GET(GET不能上传文件) 表单 enctype 属 ...

  2. Shiro authentication for Apache Zeppelin

    Overview Apache Shiro is a powerful and easy-to-use Java security framework that performs authentica ...

  3. ASP.NET 前端数据绑定---<%#%>及Eval()的使用

    ASP.NET 前端html代码中会经常出现的<%%>的代码,里面的文本其实就是不能直接输出到客户端浏览器的文本,是需要服务器解释的. 在ASP中,<%%>里面的文本是vbsc ...

  4. SP1805 HISTOGRA - Largest Rectangle in a Histogram 题解

    题目链接:https://www.luogu.org/problemnew/show/SP1805 分析: 我们可以用一个单调栈由低到高来存储它的高度,并用数组对每个高度记录一下它前面(包括它自己)一 ...

  5. python 中_init_函数以及参数self

    1)class类包含: 类的属性:类中所涉及的变量 类的方法:类中函数 2)_init_函数(方法) 1.首先说一下,带有两个下划线开头的函数是声明该属性为私有,不能在类地外部被使用或直接访问. 2. ...

  6. Baozi Leetcode Solution 205: Isomorphic Strings

    Problem Statement Given two strings s and t, determine if they are isomorphic. Two strings are isomo ...

  7. Excel催化剂开源第28波-调用Google规划求解库

    在Excel催化剂的自定义函数中,有规划求解的函数,用于在一些凑数的场景,某财务工作网友向我提出的需求,例如用于凑发票额使用. 一般开发票的场景是多次采购合在一起开具,即多个订单产生后开,同时发票一般 ...

  8. junit的Test不能使用,报错信息:Test is not an annotation type

    在使用junit的Test做测试时,注解@Test报错”Test is not an annotation type”,发现是因为测试类的类名命名为了Test,所以导致错误. 测试类类名不能直接命名为 ...

  9. UltraEdit不自动生成保存备份文件(.bak)

    UltraEdit修改文件或格式化文件保存后会生成烦人的.bak文件. 去掉该功能办法如下: 高级 -> 配置 -> 文件处理 -> 备份 “保存时备份文件”选择“不备份” (Adv ...

  10. HTTP_5_通信数据转发程序:代理、网关、隧道

    HTTP通信时,除客户端和服务器之外,还有一些用于通信数据转发的应用程序,例如代理,网关,隧道.配合服务器工作. 代理 转发功能,客户端与服务器之间可有多个代理, 缓存代理:减少服务器压力,透明代理: ...