流水清清 發表於 2019-8-21 08:58:00

Ubuntu Server : 自动更新

<p><span style="font-family: Microsoft YaHei; font-size: 15px">Ubuntu(16.04/18.04) 默认会每天自动安装系统的安全更新,但是不会自动安装包的更新。本文梳理 Ubuntu 16.04/18.04 系统的自动更新机制,并介绍如何配置系统自动更新所有的包。说明:简单起见,本文中使用 Ubuntu 指代 Ubuntu 16.04/18.04。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">系统需要更新</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">当我们远程登录系统时,会收到如下图所示的更新相关的消息:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://img2018.cnblogs.com/blog/952033/201908/952033-20190819125911544-752909191.png"></span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">红框中的第一行文字说明系统中有 149 个包需要更新。第二行说明没有安全相关的包需要更新。之所以会这样,是因为 Ubuntu 默认的配置会每天自动安装安全更新而忽略其它包的更新。接下来我们就介绍 Ubuntu 中的自动更新机制。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">通过定时任务执行更新</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">Ubuntu 默认定义了 4 个 systemd unit 执行更新任务,它们分别是:</span></p>
<div class="cnblogs_code">
<pre>/lib/systemd/system/apt-daily-<span style="color: rgba(0, 0, 0, 1)">upgrade.service
</span>/lib/systemd/system/apt-daily-<span style="color: rgba(0, 0, 0, 1)">upgrade.timer
</span>/lib/systemd/system/apt-<span style="color: rgba(0, 0, 0, 1)">daily.service
</span>/lib/systemd/system/apt-daily.timer</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">其中的 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",其功能为安装更新并删除缓存在本地的更新包。</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">apt-daily.timer 默认每天触发两次,分别为 6 点和 18 点,主要是为了缓解服务器端的下载压力。我们可以根据自身业务的特点设置合适的触发时间。</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">apt-daily-upgrade.service 默认每天在 6 点触发一次,我们也可以设置为其它时间,比如午夜。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">apt.systemd.daily 脚本</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">/usr/lib/apt/apt.systemd.daily 脚本负责完成与更新相关的一系列工作,这些工作主要分为两大块:</span></p>
<ul>
<li><span style="font-family: Microsoft YaHei; font-size: 15px">检查更新并下载更新包</span></li>
<li><span style="font-family: Microsoft YaHei; font-size: 15px">安装更新并清理更新包</span></li>

</ul>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">apt.systemd.daily 脚本中调用 apt-config 命令从 /etc/apt/apt.conf.d/10periodic 文件和 /etc/apt/apt.conf.d/20auto-upgrades 读中取配变量,并根据这些变量的值来控制系统的更新策略。下面我们介绍几个比较重要的配置项。</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">隔多少天执行一次 apt-get update,默认是 1 天,0 表示不执行该操作:</span></p>
<div class="cnblogs_code">
<pre>APT::Periodic::Update-Package-Lists <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">隔多少天执行一次 apt-get upgrade --download-only 下载更新包,0 表示不执行该操作:</span></p>
<div class="cnblogs_code">
<pre>APT::Periodic::Download-Upgradeable-Packages <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">下载的更新版被缓存在目录 <strong>/var/cache/apt/archives/</strong> 中,执行升级操作时直接从缓存目录中读取包文件而不是从网络上下载。</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">隔多少天执行一次 apt-get autoclean 清除无用的更新包,0 表示不执行该操作:</span></p>
<div class="cnblogs_code">
<pre>APT::Periodic::AutocleanInterval <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">隔多少天执行一次 Unattended-Upgrade 执行系统安全更新(或者所以包的更新),0 表示不执行该操作:</span></p>
<div class="cnblogs_code">
<pre>APT::Periodic::Unattended-Upgrade <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">通过这些配置,我们可以控制自动更新的频率和行为。注意,到目前为止的配置还只能安装系统的安全更新,如果要想安装所有包的更新还需要其它的配置,相关内容我们在后面的小节中介绍。</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在继续介绍后面的内容前,让我们先来了解一下 apt.systemd.daily 脚本中用到的 apt-config 命令和 apt.systemd.daily 脚本依赖的配置文件。</span></p>
<p><strong><span style="font-family: Microsoft YaHei; font-size: 15px">apt-config 命令</span></strong><br><span style="font-family: Microsoft YaHei; font-size: 15px">apt-config 是一个被 APT 套件使用的内部命令,使用它可以在脚本中提取 /etc/apt/apt.conf 目录下配置文件中的信息。</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">比如,如果要在脚本中获取 APT::Periodic::Update-Package-Lists 的设置,可以使用下面的代码:</span></p>
<div class="cnblogs_code">
<pre>#!/bin/<span style="color: rgba(0, 0, 0, 1)">bash
ABC</span>=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
eval $(apt</span>-config shell ABC APT::Periodic::Update-Package-<span style="color: rgba(0, 0, 0, 1)">Lists)
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> ${ABC}</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">此时脚本变量 ABC 中保存的就是 APT::Periodic::Update-Package-Lists 的值。</span></p>
<p><strong><span style="font-family: Microsoft YaHei; font-size: 15px">10periodic 和 20auto-upgrades</span></strong><br><span style="font-family: Microsoft YaHei; font-size: 15px">/etc/apt/apt.conf.d/10periodic 是 update-notifier-common 的配置文件:</span></p>
<div class="cnblogs_code">
<pre>$ dpkg-query -S /etc/apt/apt.conf.d/<span style="color: rgba(0, 0, 0, 1)">10periodic
update</span>-notifier-common: /etc/apt/apt.conf.d/10periodic</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在 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 命令根据文件名称的顺序,排在后面的文件中的变量会覆盖前面文件中的变量。</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">在 desktop 版本中,通过 GUI 程序修改相关的变量,这两个文件都会被修改并保持一致,所以在 server 版中我们最好也同时修改这两个文件并保持其内容一致。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">unattended-upgrades</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">Ubuntu 实际上是通过 unattended-upgrades 命令来自动安装更新的。Ubuntu 16.04/18.04 默认安装了这个包,如果碰到没有安装的情况你还可以通过下面的命令自行安装:</span></p>
<div class="cnblogs_code">
<pre>$ <span style="color: rgba(0, 0, 255, 1)">sudo</span> apt <span style="color: rgba(0, 0, 255, 1)">install</span> unattended-upgrades</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">unattended-upgrades 的配置文件为 <strong>/etc/apt/apt.conf.d/50unattended-upgrades</strong>。</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">注意,unattended-upgrades 不仅能够安装系统的安全更新,还可以安装所有包的更新。但是默认的配置只安装安全更新,我们可以通过配置项让 unattended-upgrades 安装所有的包更新或者只安装安全更新。</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">unattended-upgrades 命令被设计为通过 cron 定时执行系统更新,但在 Ubuntu 16.04/18.04 中是通过 systemd 的 timer unit 定时触发 service unit 执行的。</span><br><strong><span style="font-family: Microsoft YaHei; font-size: 15px">unattended-upgrades 命令的日志文件存放在 /var/log/unattended-upgrades 目录下。</span></strong></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">unattended-upgrade 命令常见的用法之一是检查系统是否有更新:</span></p>
<div class="cnblogs_code">
<pre>$ <span style="color: rgba(0, 0, 255, 1)">sudo</span> unattended-upgrade --dry-run</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">另一种用法是安装更新:</span></p>
<div class="cnblogs_code">
<pre>$ <span style="color: rgba(0, 0, 255, 1)">sudo</span> unattended-upgrade</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在 apt.systemd.daily 脚本中执行 unattended-upgrade 命令时,由于更新包已经提前下载到缓存目录了(/var/cache/apt/archives),所以直接它直接使用缓存中的更新包。</span></p>
<p><strong><span style="font-family: Microsoft YaHei; font-size: 15px">配置文件 50unattended-upgrades</span></strong><br><span style="font-family: Microsoft YaHei; font-size: 15px">50unattended-upgrades 文件中的默认配置只是安装安全更新:</span></p>
<div class="cnblogs_code">
<pre>Unattended-Upgrade::Allowed-<span style="color: rgba(0, 0, 0, 1)">Origins {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">${distro_id}:${distro_codename}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">${distro_id}:${distro_codename}-security</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">${distro_id}ESM:${distro_codename}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(255, 0, 0, 1)"><strong>//      "${distro_id}:${distro_codename}-updates";
</strong></span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">      "${distro_id}:${distro_codename}-proposed";
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">      "${distro_id}:${distro_codename}-backports";</span>
};</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">如果要自动安装所有包的更新,只要取消下面行的注释就行了:</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">"${distro_id}:${distro_codename}-updates";</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">我们还可以通过黑名单的方式指定不更新哪些包:</span></p>
<div class="cnblogs_code">
<pre>Unattended-Upgrade::Package-<span style="color: rgba(0, 0, 0, 1)">Blacklist {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">vim</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">libc6</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">libc6-dev</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">libc6-i686</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
};</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">下面的配置项指定在更新后移除无用的包:</span></p>
<div class="cnblogs_code">
<pre>Unattended-Upgrade::Remove-Unused-Kernel-Packages <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
Unattended</span>-Upgrade::Remove-Unused-Dependencies <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">有些更新需要重启系统,而默认的配置是不重启系统的。下面的配置允许重启系统(更新完成后,如果需要重启,立即重启系统):</span></p>
<div class="cnblogs_code">
<pre>Unattended-Upgrade::Automatic-Reboot <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">但是多数情况下我们更期望指定一个时间让系统重启(如果需要重启,在下面配置中指定的时间重启系统):</span></p>
<div class="cnblogs_code">
<pre>Unattended-Upgrade::Automatic-Reboot-Time <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">02:38</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在系统更新的过程中发生了错误怎么办?当然是通知管理员啦!下面的配置在发生错误时给管理员发送邮件:</span></p>
<div class="cnblogs_code">
<pre>Unattended-Upgrade::Mail <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">user@example.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
Unattended</span>-Upgrade::MailOnlyOnError <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">注意:如果要向外网发送邮件,需要安装 mailx 等工具。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">关闭自动更新</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">如果你的主机运行在封闭的环境中,并且无法连接到有效的更新源,此时可以选择关闭自动更新功能。首选的方法是停止相关的服务:</span></p>
<div class="cnblogs_code">
<pre>$ <span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl stop apt-<span style="color: rgba(0, 0, 0, 1)">daily.service
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl stop apt-<span style="color: rgba(0, 0, 0, 1)">daily.timer
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl stop apt-daily-<span style="color: rgba(0, 0, 0, 1)">upgrade.service
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl stop apt-daily-<span style="color: rgba(0, 0, 0, 1)">upgrade.timer
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl disable apt-<span style="color: rgba(0, 0, 0, 1)">daily.service
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl disable apt-<span style="color: rgba(0, 0, 0, 1)">daily.timer
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl disable apt-daily-<span style="color: rgba(0, 0, 0, 1)">upgrade.service
$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> systemctl disable apt-daily-upgrade.timer</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">或者修改自动更新程序的配置文件也可以,同时更新 /etc/apt/apt.conf.d/10periodic 和 /etc/apt/apt.conf.d/20auto-upgrades:</span></p>
<div class="cnblogs_code">
<pre>APT::Periodic::Update-Package-Lists <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
APT::Periodic::Unattended</span>-Upgrade <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">改为</span></p>
<div class="cnblogs_code">
<pre>APT::Periodic::Update-Package-Lists <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
APT::Periodic::Unattended</span>-Upgrade <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">故障调查</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">因为 apt.systemd.daily 脚本同时调用了 apt-get 和 unattended-upgrade 等命令,所以相关的日志也分散在不同的地方。apt-get 相关的日志在 /var/log/apt 目录下,unattended-upgrade 命令的日志在 /var/log/unattended-upgrades 目录下。</span></p>
<p><strong><span style="font-family: Microsoft YaHei; font-size: 15px">参考:</span></strong><br><span style="font-family: Microsoft YaHei; font-size: 15px">unattended-upgrade man page</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">Automatic Updates</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">AutomaticSecurityUpdates</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">apt-config man page</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">如何在Ubuntu 16.04上安装自动安全更新</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">How to set up automatic updates on Ubuntu Server 18.04</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">Ubuntu Enable Automatic Updates Unattended Upgrades</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">Ubuntu 16.04: Auto apt update and apt upgrade</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">mvo5/unattended-upgrades</span></p>

</div>
<div id="MySignature" role="contentinfo">
    <div>作者:sparkdev</div>
<div>出处:http://www.cnblogs.com/sparkdev/</div>
<div>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。</div><br><br>
来源:https://www.cnblogs.com/sparkdev/p/11376560.html
頁: [1]
查看完整版本: Ubuntu Server : 自动更新