fix: tell unattended-upgrade from Ubuntu's idle shutdown helper
CI / test (3.10) (push) Successful in 24s
CI / test (3.11) (push) Successful in 23s
CI / test (3.12) (push) Successful in 24s
CI / test (3.10) (pull_request) Successful in 24s
CI / test (3.11) (pull_request) Successful in 22s
CI / test (3.12) (pull_request) Successful in 25s

On every Ubuntu host with unattended-upgrades, get_host_status() read the
package manager as busy, so an interrupted dpkg was never reported there.
Ubuntu keeps unattended-upgrade-shutdown --wait-for-signal running all the
time; its process name is cut to 15 characters, unattended-upgr, the same
as a real run's.

BUSY_CHECK now matches dpkg, apt, apt-get and aptitude by name and
unattended-upgrade by its command line. The tests run it through sh with a
stand-in ps, and check that the command does not match itself: over an exec
channel it is the command line of the shell that runs it.

Closes #26
This commit is contained in:
christianmanivong committed 2026-10-08 17:30:44 +02:00
1 parent 72679ff4f8
commit 7aa731ad34
3 files changed
+67 -6

No files matched your search

+13 -5
View File
@@ -39,7 +39,8 @@ anything until ``dpkg --configure -a`` has run, while ``apt.systemd.daily``
exits quietly every day (NetOrk/netork#738). While dpkg, apt, aptitude or
unattended-upgrade is running, packages are halfway on purpose -- also between
two of apt's dpkg calls -- so the answer is then ``None``, as on a host without
dpkg.
dpkg. unattended-upgrade is told from Ubuntu's idle shutdown helper by its
command line (:data:`BUSY_CHECK`).
"""
from __future__ import annotations
@@ -57,9 +58,16 @@ _APT_TIMER = "apt-daily-upgrade.timer"
_DNF_TIMERS = ("dnf-automatic.timer", "dnf-automatic-install.timer")
_UPGRADE_STAMP = "/var/lib/apt/periodic/upgrade-stamp"
_DPKG_JOURNAL = "/var/lib/dpkg/updates"
#: The processes that leave packages halfway while they work (``comm``, at most
#: 15 characters: unattended-upgrade shows as ``unattended-upgr``).
_PACKAGE_MANAGERS = "dpkg|apt|apt-get|aptitude|unattended-upgr"
#: Prints ``[dpkg-busy]`` while a process that leaves packages halfway is working:
#: dpkg, apt, apt-get or aptitude by name, unattended-upgrade by its command line.
#: Its name is cut to 15 characters, ``unattended-upgr``, the same as that of
#: ``unattended-upgrade-shutdown --wait-for-signal``, which Ubuntu keeps running all
#: the time and which installs nothing.
BUSY_CHECK = (
"{ ps -e -o comm= 2>/dev/null | grep -qxE 'dpkg|apt|apt-get|aptitude' || "
"ps -e -o args= 2>/dev/null | grep -qE '(^|[ /])unattended-upgrade( |$)'; } "
"&& echo '[dpkg-busy]'; "
)
#: One line, POSIX ``sh``, read-only, no privileges. The frame markers are
#: printed in two halves so that an echoing transport does not show them early.
@@ -79,7 +87,7 @@ HOST_STATUS_COMMAND = (
"apt-config dump 2>/dev/null | grep '^APT::Periodic::Unattended-Upgrade '; "
f"echo '[upgrade-stamp]'; stat -c %Y {_UPGRADE_STAMP} 2>/dev/null; fi; "
"if command -v dpkg-query >/dev/null 2>&1; then "
f"ps -e -o comm= 2>/dev/null | grep -qxE '{_PACKAGE_MANAGERS}' && echo '[dpkg-busy]'; "
f"{BUSY_CHECK}"
f"echo '[dpkg-journal]'; ls -1 {_DPKG_JOURNAL} 2>/dev/null | head -n 20; "
"echo '[dpkg-audit]'; dpkg-query -W -f='${db:Status-Abbrev} ${Package}\\n' 2>/dev/null "
"| awk 'substr($0, 2, 1) ~ /[HUFWt]/ || substr($0, 3, 1) == \"R\"' | head -n 50; fi; "