Hoy tuve la necesidad de listar paquetes por repositorio en un servidor Debian 6. Determinar qué paquetes fueron instalados desde un repositorio en particular. Descubrí que no es una tarea sencilla en absoluto. Por ello decidí escribir este breve artículo, para tener a mano el comando en caso de necesitar utilizarlo en el futuro.
En Debian y derivados, normalmente se utiliza el comando dpkg -l | grep '^ii'
para listar los paquetes instalados. Aunque la salida de este comando no contiene información acerca de qué repositorio proviene cada paquete. La herramienta apt-cache
provee dicha información, pero no permite listar paquetes por repositorio, por lo tanto sólo es posible filtrar manualmente.
Veamos un ejemplo en un sistema Debian 6:
root@debian6:~# cat /etc/issue Debian GNU/Linux 6.0 \n \l
Cuando se me planteó esta necesidad, la primera opción que probé fue utilizar la herramienta dpkg-query
, la cual, según su página de manual, posee la opción -W
para listar todos los paquetes (cuando no se especifica ningún patrón), y la opción -f
para formatear su salida:
root@debian6:~# man dpkg-query
-W, --show package-name-pattern... Just like the --list option this will list all packages match- ing the given pattern. However the output can be customized using the --showformat option. The default output format gives one line per matching package, each line having the name and installed version of the package, separated by a tab.
-f, --showformat=format This option is used to specify the format of the output --show will produce. The format is a string that will be output for each package listed.
Y entre las opciones de formato es posible obtener el origen (repositorio) de cada paquete:
Maintainer Origin Package
Lamentablemente descubrí que, a pesar de que se dispone de esta opción, no existe la información:
root@debian6:~# dpkg-query -W -f='${Package} ${Origin}\n' | head acpi acpi-support-base acpid adduser aide aide-common apache2 apache2-mpm-worker apache2-threaded-dev apache2-utils
En cambio sí existe para otros campos:
root@debian6:~# dpkg-query -W -f='${Package} ${Maintainer}\n' | head acpi Debian Acpi Team <pkg-acpi-devel@lists.alioth.debian.org> acpi-support-base Debian Acpi Team <pkg-acpi-devel@lists.alioth.debian.org> acpid Debian Acpi Team <pkg-acpi-devel@lists.alioth.debian.org> adduser Debian Adduser Developers <adduser-devel@lists.alioth.debian.org> aide Aide Maintainers <pkg-aide-maintainers@lists.alioth.debian.org> aide-common Aide Maintainers <pkg-aide-maintainers@lists.alioth.debian.org> apache2 Debian Apache Maintainers <debian-apache@lists.debian.org> apache2-mpm-worker Debian Apache Maintainers <debian-apache@lists.debian.org> apache2-threaded-dev Debian Apache Maintainers <debian-apache@lists.debian.org> apache2-utils Debian Apache Maintainers <debian-apache@lists.debian.org>
Por lo tanto debí probar otra solución: obtener el listado de todos los paquetes instalados y ejecutar apt-cache show
sobre cada uno, para luego filtrar por repositorio. Por ejemplo, si quisiera determinar qué paquetes han sido instalados desde el repositorio "lts" simplemente debo ejecutar:
root@debian6:~# for p in $(dpkg -l | grep '^ii' | cut -d ' ' -f 3); do apt-cache showpkg $p | head -3 | grep -v '^Versions' | sed -e 's/Package: //;' | paste - - ; done | grep lts | awk -F '\t' '{print $1}' | head acpi-support-base apache2 apache2-mpm-worker apache2-threaded-dev apache2-utils apache2.2-bin apache2.2-common apt apt-utils bash
En el sistema en cuestión, 34 paquetes (instalados) provienen del repositorio "backports":
root@debian6:~# for p in $(dpkg -l | grep '^ii' | cut -d ' ' -f 3); do apt-cache showpkg $p | head -3 | grep -v '^Versions' | sed -e 's/Package: //;' | paste - - ; done | grep backports | wc -l 34
¿Qué hace éste comando?
for p in $(dpkg -l | grep '^ii' | cut -d ' ' -f 3); do apt-cache showpkg $p | head -3 | grep -v '^Versions' | sed -e 's/Package: //;' | paste - - ; done | grep lts | awk -F '\t' '{print $1}'
Primero obtiene un listado de todos los paquetes instalados quedándose sólo con el nombre del paquete: dpkg -l | grep '^ii' | cut -d ' ' -f 3
Luego, para cada uno (for p in $
), obtiene su información detallada: apt-cache showpkg $p
En la salida de apt-cache showpkg
, la primera línea es el nombre del paquete y de la tercera se puede deducir el origen. Por ende, se obtienen sólo las primeras 3 líneas (head -3
), se elimina la segunda línea (grep -v '^Versions'
), se elimina la cadena "Package: " de la primera línea (sed -e 's/Package: //;'
), y se concatenan ambas líneas (paste - -
).
Hasta aquí se obtiene un listado donde cada línea posee el nombre del paquete y su origen. Sólo resta filtrar de acuerdo al repositorio deseado, por ejemplo "lts" (grep lts
), "backports", "updates", etc. Luego es posible quedarse sólo con los nombres de paquete (awk -F '\t' '{print $1}'
) o con el total (wc -l
).
De esta forma fui capaz de identificar qué paquetes fueron instalados desde el repositorio "lts".
Espero que les sirva.