如何判断哪些软件包因为分阶段更新而被推迟。

我已经寻找这个问题的答案很长时间了,虽然我看到了一些提出的解决方案,但都没有起作用。
使用这个命令,我可以看到所有准备更新的软件包:
apt list --upgradable

有些软件因为分阶段更新而被推迟升级。我想知道哪些软件将会升级,哪些会被推迟。
目前我所知的方法就是执行以下命令(每个软件包执行一次):
apt-cache policy [packagename]

如果输出中包含字符串(phased …%)(在百分比符号之前有一位、两位或三位数字),这意味着该软件包是分阶段更新的一部分。但它并不能告诉我它是否会立即安装在我的计算机上。
我怎么知道哪些待处理的软件包会立即安装,哪些由于分阶段更新而被推迟安装?
我运行的是Ubuntu 22.04,如果这有所不同,请帮助解答。
谢谢。
3个回答

我还拼凑了一些命令。主要是使用awk来解析apt的输出,但如果有人熟悉更本地的命令就太好了。
如果你想找出所有正在进行分阶段更新以及它们关联的阶段百分比的软件包。
apt-cache dumpavail | awk '/^Package: /{p=$2} /^Phased-Update-Percentage/{print p,$2}'

然而,根据你的问题,你可能只关心正在进行分阶段更新的已安装软件包。
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}}'

你还可以找到将被保留的软件包。在这种情况下,是在进行完全升级时。
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]}}'

但是你想要“立即告诉哪些待处理的软件包将被安装,哪些由于分阶段更新而被推迟”。把它们整合在一起。
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"}}}'

这是在最近打了补丁的22.04服务器上的样本输出(管道传输到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

结果与full-upgrade输出相匹配
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

注意事项

  • 我在Ubuntu 22.04上使用apt 2.4.8测试了这些命令。
  • 这些命令可能无法处理某些情况。
  • 这不是一个快速解决方案,在我的最低规格虚拟机上运行需要超过10秒的时间。
  • 处理分阶段更新的方式似乎正在发生变化。在深入研究之前,我使用apt-cache policy来确定一个软件包是否被拦截。然而,这种方法不再可靠。我找到了一个apt配置选项APT::Get::Phase-Policy=True,它有所帮助,但结果与实际的apt行为不一致。以下是我根据apt-cache policy输出解析而得到的结果,但与apt的实际行为不匹配
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

1这个回答非常详尽,谢谢你! - Paddy Landau
第三个有点小问题。如果只有一些软件包被阻止更新,而没有需要升级的软件包,返回的列表就是无意义的。我不懂awk,所以不知道该如何修复这个问题! - Paddy Landau
1我调整了awk的设置,以处理没有升级项时的情况。我很想进行其他优化,但解析输出始终是一个脆弱的设置。 - Andrew Lowther
谢谢你,@Andrew Lowther - Paddy Landau

这是一种方式:
//The list of all upgradeable packages

$ apt list --upgradeable | cut -d'/' -f1
Listing...
tcpdump
ubuntu-advantage-tools

//The list of upgradeable packages that are NOT phased
//...or are phasing, and it's your turn for install

$ apt upgrade --simulate | grep Inst | cut -d' ' -f2
ubuntu-advantage-tools

当然,相位包的列表就是这些列表之间的差异。

太好了,谢谢你。我希望我能给两个不同的答案打上绿色勾号,因为这个也值得。 - Paddy Landau
+1 "阶段性软件包列表当然是两个列表之间的差异。"... 即使翻译成代码,例如:comm -3 <(apt upgrade --simulate | grep Inst | cut -d' ' -f2 | sort) <(apt list --upgradeable | cut -d'/' -f1 | sort) - Raffa

执行apt upgrade命令的输出将告诉您哪些软件包将被升级,哪些软件包将被保留。
您还可以使用apt -s upgrade命令运行模拟,以获得相同的所需信息。
$ apt -s upgrade
NOTE: This is only a simulation!
      apt needs root privileges for real execution.
      Keep also in mind that locking is deactivated,
      so don't depend on the relevance to the real current situation!
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
Get more security updates through Ubuntu Pro with 'esm-apps' enabled:
  libimage-magick-perl imagemagick libdcmtk16 libopenexr25 libmagick++-6.q16-8
  libmagickcore-6.q16-6-extra libimage-magick-q16-perl libmagickwand-6.q16-6
  imagemagick-6.q16 libeditorconfig0 libmagickcore-6.q16-6
  imagemagick-6-common
Learn more about Ubuntu Pro at https://ubuntu.com/pro
The following packages have been kept back:
  grub-efi-amd64 grub-efi-amd64-bin grub-efi-amd64-signed libsasl2-2 libsasl2-modules libsasl2-modules-db
  libsnmp-base libsnmp40 shim-signed tcpdump
0 upgraded, 0 newly installed, 0 to remove and 10 not upgraded.