Ubuntuのunattended-upgradesを調べてみた

Ubuntuバージョン

以下のバージョンで動きを確認しました。

$ uname -v
#71~20.04.1-Ubuntu SMP Thu Jul 15 17:46:08 UTC 2021

パッケージ情報

パッケージ情報です。

GitHub

github.com

apt info

$ apt info -a unattended-upgrades
Package: unattended-upgrades
Version: 2.3ubuntu0.1
Priority: optional
Section: admin
Origin: Ubuntu
Maintainer: Ubuntu Developers <[email protected]>
Original-Maintainer: Michael Vogt <[email protected]>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 451 kB
Depends: debconf (>= 0.5) | debconf-2.0, debconf, python3, python3-apt (>= 1.9.6~), python3-dbus, python3-distro-info, ucf, lsb-release, lsb-base, xz-utils
Recommends: systemd-sysv | cron | cron-daemon | anacron
Suggests: bsd-mailx, default-mta | mail-transport-agent, needrestart, powermgmt-base, python3-gi
Task: server, ubuntu-desktop-minimal, ubuntu-desktop, cloud-image, kubuntu-desktop, xubuntu-core, xubuntu-desktop, lubuntu-desktop, ubuntustudio-desktop-core, ubuntustudio-desktop, ubuntukylin-desktop, ubuntu-mate-core, ubuntu-mate-desktop, ubuntu-budgie-desktop
Download-Size: 48.7 kB
APT-Manual-Installed: yes
APT-Sources: http://jp.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
Description: セキュリティ更新の自動インストール
 本パッケージによりセキュリティ更新を自動かつ無人でダウンロードおよび インストールすることができます。設定された APT
 ソースに由来するインストール 済みパッケージのみを取り扱い、設定ファイル変更に関する dpkg プロンプトを チェックします。
 .
 本スクリプトは APT:Periodic:Unattended-Upgrade オプションのバックエンド です。

スケジューリング

anacron (今は使われていない)

WEBで調べているとanacronで実行されているように書かれている記事もあり、実際に以下のファイルが登録されています。

/etc/cron.daily/apt-compat

ただ、中身を見るとわかるのですが、最初にsystemd存在確認が走り、systemdのあるシステムの場合は空振りするようになっています。

$ cat /etc/cron.daily/apt-compat | head -n 13
#!/bin/sh

set -e

# Systemd systems use a systemd timer unit which is preferable to
# run. We want to randomize the apt update and unattended-upgrade
# runs as much as possible to avoid hitting the mirrors all at the
# same time. The systemd time is better at this than the fixed
# cron.daily time
if [ -d /run/systemd/system ]; then
    exit 0
fi

systemdによるスケジュール

anacronのコメントに書いてある通り、現在はSystemdでスケジュールされているようです。 自動更新のスケジュールは以下のコマンドで確認できます。

スケジュール確認

systemctl list-timers コマンドを使うとTimerの一覧を確認できます。 unattended-upgrade に関連するのは apt-dailyapt-daily-upgrade の二つです。

$ systemctl list-timers --all
NEXT                        LEFT          LAST                        PASSED        UNIT                         ACTIVATES
# 省略
Tue 2021-07-27 04:59:09 JST 5h 56min left Mon 2021-07-26 07:49:08 JST 15h ago       apt-daily.timer              apt-daily.service
Tue 2021-07-27 06:28:11 JST 7h left       Mon 2021-07-26 06:34:08 JST 16h ago       apt-daily-upgrade.timer      apt-daily-upgrade.service
# 省略
スケジュール設定(Systemd Timerファイル)

スケジュールが設定されているtimerファイルの中身は以下のようになります。

$ cat /etc/systemd/system/timers.target.wants/apt-daily.timer
[Unit]
Description=Daily apt download activities

[Timer]
OnCalendar=*-*-* 6,18:00
RandomizedDelaySec=12h
Persistent=true

[Install]
WantedBy=timers.target
$ cat /etc/systemd/system/timers.target.wants/apt-daily-upgrade.timer
[Unit]
Description=Daily apt upgrade and clean activities
After=apt-daily.timer

[Timer]
OnCalendar=*-*-* 6:00
RandomizedDelaySec=60m
Persistent=true

[Install]
WantedBy=timers.target
スケジュール設定

スケジュール設定はsystemdのTimer定義から行います。

以下から OnCalendarRandomizedDelaySec を変更してから、 systemctl daemon-reload を実行することで設定が反映されます。

処理概要

systemd Serviceファイル

systemdのサービスファイルです。

ExecStartPre=-/usr/lib/apt/apt-helper wait-online にてオンラインになるのを待ってから、/usr/lib/apt/apt.systemd.daily をそれぞれ installupdate の引数付きで呼んでいます。

$ cat /lib/systemd/system/apt-daily-upgrade.service
[Unit]
Description=Daily apt upgrade and clean activities
Documentation=man:apt(8)
ConditionACPower=true
After=apt-daily.service network.target network-online.target systemd-networkd.service NetworkManager.service connman.service

[Service]
Type=oneshot
ExecStartPre=-/usr/lib/apt/apt-helper wait-online
ExecStart=/usr/lib/apt/apt.systemd.daily install
KillMode=process
TimeoutStopSec=900
$ cat /lib/systemd/system/apt-daily.service
[Unit]
Description=Daily apt download activities
Documentation=man:apt(8)
ConditionACPower=true
After=network.target network-online.target systemd-networkd.service NetworkManager.service connman.service

[Service]
Type=oneshot
ExecStartPre=-/usr/lib/apt/apt-helper wait-online
ExecStart=/usr/lib/apt/apt.systemd.daily update
apt.systemd.dailyスクリプト

/usr/lib/apt/apt.systemd.daily はシェルスクリプトです。サービスの名前や引数からは直感的に何しているかわからなかったので、主なコマンドを並べてみました。何となく何しているのかわかると思います。

主なコマンド以外だと /var/cache/apt のディレクトリ下の /var/cache/apt/archive/var/cache/apt/backup などを使った過去データのバックアップや世代管理なども行っています。

Service Timer ExecStart 主なコマンド
apt-daily-upgrade.service apt-daily-upgrade.timer /usr/lib/apt/apt.systemd.daily install - unattended-upgrade - apt-get clean - apt-get autoclean
apt-daily.service apt-daily.timer /usr/lib/apt/apt.systemd.daily update - apt-get update - apt-get dist-upgrade -d (-d: only download) - unattended-upgrade --download-only

パラメータ

unattended-upgradeですがパラメータで挙動を調整することが可能です。

現在のパラメータ値を確認する

まずパラメータ値を確認するには以下のコマンドを実行します。

$ apt-config dump

パラメータの設定場所

以下にパラメータの設定が集まっています。

$ ls -1 /etc/apt/apt.conf.d/
00aptitude
00trustcdrom
01-vendor-ubuntu
01autoremove
01autoremove-kernels
10periodic
15update-stamp
20archive
20auto-upgrades
20dbus
20packagekit
20snapd.conf
50appstream
50command-not-found
50unattended-upgrades
60icons
60icons-hidpi
70debconf
99update-notifier

unattended-upgradeの中身の挙動制御パラメータ

特に /etc/apt/apt.conf.d/50unattended-upgradesunattended-upgrades 自体の挙動を制御するパラメータ群となります。

/usr/bin/unattended-upgrade が`Pythonスクリプトなので、中身見ながら説明書いてみます。

パラメータ デフォルト 説明
Unattended-Upgrade::Allowed-Origins - ${distro_id}:${distro_codename}-${distro_id}:${distro_codename}-security- ${distro_id}ESMApps:${distro_codename}-apps-security- ${distro_id}ESM:${distro_codename}-infra-security [マクロ変数に入る値の例] ${distro_id} = "ubuntu" ${distro_codename} = "focal" 許可されるパッケージ取得元
Unattended-Upgrade::Package-Blacklist - 更新除外するパッケージ
Unattended-Upgrade::DevRelease auto devel releaseを自動更新するか(true/false/auto)
Unattended-Upgrade::AutoFixInterruptedDpkg true dpkg --force-confold --configure -a の自動実行を行うか
Unattended-Upgrade::InstallOnShutdown false Shutdown時に更新のインストールを行うか
Unattended-Upgrade::Mail /usr/bin/mail/usr/sbin/sendmail などで通知メールを送信するか
Unattended-Upgrade::MailReport on-change メールを送信する条件:"always", "only-on-error" or "on-change"
Unattended-Upgrade::Remove-Unused-Kernel-Packages true 利用されていないカーネル関連パッケージの削除
Unattended-Upgrade::Remove-New-Unused-Dependencies true 更新後の利用されていないパッケージの削除
Unattended-Upgrade::Automatic-Reboot false /var/run/reboot-requiredが存在する場合に自動でOS再起動
Unattended-Upgrade::Automatic-Reboot-WithUsers true Unattended-Upgrade::Automatic-Reboot が有効で再起動を実施する際に、ログオンユーザチェックを行うか。チェック時にログオンユーザがいる場合は再起動を行わない。(falseの場合にチェックを行う)
Unattended-Upgrade::Automatic-Reboot-Time now 02:00 など時間を設定することで、 /sbin/shutdown -r pram として実行される
Acquire::http::Dl-Limit 70(kb/sec) 利用帯域制限
Unattended-Upgrade::SyslogEnable false Syslogへの出力
Unattended-Upgrade::SyslogFacility daemon Syslogのファシリティ
Unattended-Upgrade::OnlyOnACPower true /usr/sbin/on_ac_power コマンドの結果を元にAC Powerでない場合は処理を中断するか
Unattended-Upgrade::Skip-Updates-On-Metered-Connections true Metered ConnectionはCellar等の従量課金などの接続を指すようで、以下のコードで判断されます。
from gi.repository.Gio import NetworkMonitor
NetworkMonitor.get_network_metered(NetworkMonitor.get_default())
Unattended-Upgrade::Verbose false ログレベルのVerboseモード
Unattended-Upgrade::Debug false debugログの出力
Unattended-Upgrade::Allow-downgrade false パッケージのダウングレードの許可

unattended-upgradeの起動パラメータ

systemdから起動時に呼ばれる /usr/lib/apt/apt.systemd.daily に設定可能なパラメータを以下に整理してみました。

パラメータ デフォルト 説明
Dir / ルートディレクトリ
Dir::Cache var/cache/apt/ キャッシュディレクトリ
Dir::Cache::Archives archives/ アーカイブディレクトリ
Dir::Cache::Backup backup/ バックアップディレクトリ
APT::Periodic::Enable 1 0 に設定すると処理がスキップされる(自動更新が止まる)
APT::Periodic::BackupArchiveInterval 0 backupフォルダにCacheのバックアップを行うか
APT::Periodic::BackupLevel 3 バックアップ世代管理パラメータ
APT::Periodic::MaxAgeAPT::Periodic::MaxAge(old, deprecated) 0 バックアップ世代管理パラメータ
APT::Periodic::MaxSizeAPT::Periodic::MaxSize(old, deprecated) 0 バックアップ世代管理パラメータ
APT::Periodic::MinAgeAPT::Periodic::MinAge(old, deprecated) 2 バックアップ世代管理パラメータ
APT::Periodic::Update-Package-Lists 0 apt-get update を何日おきに実行するか(0は無効)
APT::Periodic::Download-Upgradeable-Packages 0 apt-get upgrade --download-only を何日おきに実行するか(0は無効)
APT::Periodic::Download-Upgradeable-Packages-Debdelta 1 debdelta-upgrade でupdateをダウンロードする(0は無効)
APT::Periodic::Unattended-Upgrade 0 unattended-upgrade でセキュリティアップグレードを何日おきに実行するか(0は無効)
APT::Periodic::AutocleanInterval 0 apt-get autoclean を何日おきに実行するか(0は無効)
APT::Periodic::CleanInterval 0 apt-get clean を何日おきに実行するか(0は無効)
APT::Periodic::Verbose 0 rootユーザへのメール通知 0 : no report 1: progress report 2: command output 3: trace on

設定ファイル

通常の使い方の場合の主な設定ファイルは以下の2つです。

$ cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
/etc/apt/apt.conf.d/50unattended-upgrades

以下のように最後に読み込まれるファイルを作成して上書きすることもできます。

/etc/apt/apt.conf.d/99custom

設定後は思った通りの設定になっているか apt-config dump で確認します。

その他

unattended-upgrade-shutdownサービス

unattended-upgradeが走っている時にシャットダウンのシグナルを検知した時などのハンドリングを行うサービスです。以下のようにSystemdで定義されています。

$ cat /etc/systemd/system/multi-user.target.wants/unattended-upgrades.service
[Unit]
Description=Unattended Upgrades Shutdown
After=network.target local-fs.target systemd-logind.service
RequiresMountsFor=/run /var/log /var/run /var/lib /boot
Documentation=man:unattended-upgrade(8)

[Service]
ExecStart=/usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
KillMode=process
TimeoutStopSec=1800

[Install]
WantedBy=multi-user.target

ExecStart見るとわかる通り、実行されている /usr/share/unattended-upgrades/unattended-upgrade-shutdown はPythonスクリプトなので中身を見ると何しているかわかりやすいです。

ログの場所

デフォルトでは以下にログが出力されます。

$ ls -1 /var/log/unattended-upgrades
unattended-upgrades-dpkg.log
unattended-upgrades-dpkg.log.1.gz
unattended-upgrades-shutdown.log
unattended-upgrades-shutdown.log.1.gz
unattended-upgrades.log
unattended-upgrades.log.1.gz

マニュアル実行

# -d を付けてログ出力ありで実行
$ sudo unattended-upgrade -d

# --dry-runもあります
$ sudo unattended-upgrade -d --dry-run