From 0f44340efed197d245daa28d891cc0fc089190f4 Mon Sep 17 00:00:00 2001 From: Preston Hunt Date: Fri, 28 Aug 2026 12:24:45 -0700 Subject: [PATCH] apt: anchor the inhibitor pattern and bound the kill loop 'pgrep -f apt|aptd|unattended-upgrade' matched the pattern anywhere in any process's full command line. That catches unrelated processes whose arguments happen to contain "apt", and -- because the pattern is itself an argument to the sudo/pkill pair this function spawns -- the function could match and signal its own helpers. Anchor the alternation at the start of the command line with an optional /usr/bin or /usr/sbin prefix and a word boundary at the end, and stop the responsible systemd units first, which is what actually schedules these jobs. Also replace the unbounded 'while pgrep' with a bounded 20-iteration loop so an unkillable process degrades to a warning instead of hanging the script, silence the pgrep PID output, and make $unwanted local. Verified the new pattern matches 'apt-get update', '/usr/bin/apt-get install', 'aptd' and 'unattended-upgrade --download-only' while rejecting its own pkill command line, gnome-terminal-server and snapd. Co-Authored-By: Claude Opus 5 (1M context) --- setup | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/setup b/setup index df939ed..78a395e 100755 --- a/setup +++ b/setup @@ -137,11 +137,30 @@ change_hostname() { } kill_apt_inhibitors() { - unwanted='apt|aptd|unattended-upgrade' - while pgrep -f "$unwanted"; do - sudo pkill -f "$unwanted" ||: + : "stop background apt jobs that hold the dpkg lock" + + # Ask systemd first -- these units are what schedule the offenders, + # so stopping them is both gentler and more reliable than SIGTERM. + _systemctl stop unattended-upgrades.service apt-daily.service \ + apt-daily-upgrade.service packagekit.service &>/dev/null ||: + + # Anchor the pattern at the start of the command line. The previous + # 'apt|aptd|unattended-upgrade' was an unanchored substring match + # against the full cmdline, so it matched any process whose + # arguments merely contained "apt" -- including the sudo and pkill + # processes this function itself spawns, since the pattern is one of + # their arguments. + local unwanted='^(/usr/s?bin/)?(apt|apt-get|aptd|unattended-upgrade)([[:space:]]|$)' + local tries + + # Bounded: never spin forever on a process we are unable to kill. + for (( tries = 0; tries < 20; tries++ )); do + pgrep -f "$unwanted" &>/dev/null || return 0 + sudo pkill -f "$unwanted" &>/dev/null ||: sleep 0.5 done + + info "warning: apt still running after 10s; continuing anyway" } make_journald_persistent() {