I also cobbled together some commands. I am mostly parsing apt
output using awk
but it would be great if somebody else knows more native commands.
If you want to find all the packages going through phased updates and their associated phase percentage.
apt-cache dumpavail | awk '/^Package: /{p=$2} /^Phased-Update-Percentage/{print p,$2}'
However, based on the question you probably only care about installed packages that are going through phased updates.
apt-cache dumpavail | awk '/^Package: /{p=$2} /^Phased-Update-Percentage/{cmd="dpkg -l "p" 2>&1 | grep -c ^ii";cmd | getline out;close(cmd); if(out > 0){print p,$2}}'
You can also find the packages that will be held back. In this case, during a full-upgrade
.
apt-get --simulate full-upgrade | awk '/^The following packages have been kept back:/{save=1;next} /^[[:graph:]]/{save=0;next} save{kp=kp$0} END{split(kp,kpa);for(kpi in kpa){print kpa[kpi]}}'
But then you want to "tell which of the pending packages would be installed right now, and which ones would be held back due to phased updates". Putting it all together.
apt-cache dumpavail |
awk -v OFS="," -v kp="$(
apt-get --simulate full-upgrade | awk '/^The following packages have been kept back:/{save=1;next} /^[[:graph:]]/{save=0;next} save{kp=kp$0} END{print kp}'
)" \
'BEGIN{split(kp,kpa);for(kpi in kpa){kpd[kpa[kpi]]=""}} /^Package: /{p=$2} /^Phased-Update-Percentage/{cmd="dpkg -l "p" 2>&1 | grep -c ^ii";cmd | getline out;close(cmd); if(out > 0){if(p in kpd){print p,"phased "$2,"held back"}else{print p,"phased "$2,"not held back"}}}'
Here is sample output on a fairly recently patched 22.04 server (piping into column
).
root@ubuntu:~# apt-cache dumpavail | awk -v OFS="," -v kp="$(apt-get --simulate full-upgrade | awk '/^The following packages have been kept back:/{save=1;next} /^[[:graph:]]/{save=0;next} save{kp=kp$0} END{print kp}')" 'BEGIN{split(kp,kpa);for(kpi in kpa){kpd[kpa[kpi]]=""}} /^Package: /{p=$2} /^Phased-Update-Percentage/{cmd="dpkg -l "p" 2>&1 | grep -c ^ii";cmd | getline out;close(cmd); if(out > 0){if(p in kpd){print p,"phased "$2,"held back"}else{print p,"phased "$2,"not held back"}}}' | column -t -s ,
grub-efi-amd64-bin phased 0 held back
grub-efi-amd64-signed phased 0 held back
libmbim-glib4 phased 70 held back
libmbim-proxy phased 70 held back
libmm-glib0 phased 70 not held back
libqmi-glib5 phased 70 held back
libqmi-proxy phased 70 held back
libsasl2-2 phased 70 held back
libsasl2-modules phased 70 held back
libsasl2-modules-db phased 70 held back
modemmanager phased 70 held back
python3-software-properties phased 0 held back
shim-signed phased 62 held back
software-properties-common phased 0 held back
tcpdump phased 20 not held back
ubuntu-advantage-tools phased 20 held back
The results match the full-upgrade
output
root@ubuntu:~# apt-get --simulate full-upgrade
...
The following packages have been kept back:
grub-efi-amd64-bin grub-efi-amd64-signed libmbim-glib4 libmbim-proxy libqmi-glib5 libqmi-proxy libsasl2-2 libsasl2-modules libsasl2-modules-db modemmanager python3-software-properties shim-signed software-properties-common ubuntu-advantage-tools
The following packages will be upgraded:
isc-dhcp-client isc-dhcp-common libmm-glib0 tcpdump
notes
- I tested these commands on Ubuntu 22.04 with apt
2.4.8
.
- There are likely scenarios these commands will not handle.
- This is not a fast solution and takes over 10s to run on my minimal spec VM.
- The way phased updates are handled seems to be changing. Before going down this rabbit-hole I used
apt-cache policy
to determine whether a package was held back or not. That no longer appears reliable. I found an apt configuration option APT::Get::Phase-Policy=True
that helps, but the results are not consistent with actual apt behavior. This was the output I generated when parsing the output of apt-cache policy
, but it does not match what apt would do.
root@ubuntu:~# for i in $(apt-cache dumpavail | awk '/^Package: /{p=$2} /^Phased-Update-Percentage/{cmd="dpkg -l "p" 2>&1 | grep -c ^ii";cmd | getline out;close(cmd); if(out > 0){print p}}'); do apt-cache -o=APT::Get::Phase-Policy=True policy $i | awk -v p=$i 'NR==2{iv=$2} NR==3{cv=$2} /phased/{pv=$1;pp=$3" "$4;exit} END{if( cv == pv ) { printf "%s,%s,not held back\n",p,pp }else{printf "%s,%s,held back\n",p,pp}}'; done | column -t -s ,
grub-efi-amd64-bin (phased 0%) held back
grub-efi-amd64-signed (phased 0%) held back
libmbim-glib4 (phased 70%) held back
libmbim-proxy (phased 70%) held back
libmm-glib0 (phased 70%) not held back
libqmi-glib5 (phased 70%) not held back
libqmi-proxy (phased 70%) not held back
libsasl2-2 (phased 70%) held back
libsasl2-modules (phased 70%) held back
libsasl2-modules-db (phased 70%) held back
modemmanager (phased 70%) not held back
python3-software-properties (phased 0%) held back
shim-signed (phased 62%) held back
software-properties-common (phased 0%) held back
tcpdump (phased 20%) not held back
ubuntu-advantage-tools (phased 20%) held back
awk
, and so I don't know how to fix this! – Paddy Landau Mar 04 '23 at 08:42