Nota: Este artículo lo comencé a escribir hace mucho tiempo, pero al estar basado en los paquetes de la rama testing de Debian, la información aquí recogida cambiaba a la vez que cambiaban los paquetes y sus dependencias. Es por ello que he preferido esperar hasta la versión estable de Debian "Jessie" para publicarlo.
Utilizando los superpoderes que nos proporciona aptitude
voy a realizar una pequeña radiografía de los paquetes que tengo
instalados en mi actual Debian. El objetivo es usar más tarde dicha
información para simplificar la instalación y limpiarla de paquetes
innecesarios.
Para entender el origen de la instalación de un paquete cualquiera, lo más directo es echar un vistazo a su descripción1:
$ LANG=C aptitude show gzip
Package: gzip
Essential: yes
State: installed
Automatically installed: no
Version: 1.6-4
Priority: required
Section: utils
Maintainer: Bdale Garbee <bdale@gag.com>
Architecture: amd64
Uncompressed Size: 245 k
Depends: dpkg (>= 1.15.4) | install-info
PreDepends: libc6 (>= 2.17)
Suggests: less
Conflicts: gzip
Description: GNU compression utilities
This package provides the standard GNU file compression utilities, which are
also the default compression tools for Debian. They typically operate on files
with names ending in '.gz', but can also decompress files ending in '.Z'
created with 'compress'.
Tags: implemented-in::c, interface::commandline, role::program, scope::utility,
suite::gnu, use::compressing, works-with::archive, works-with::file
Los campos en los que fijarse son Essential:
, Priority:
y
Automatically installed:
. Los términos de búsqueda (search terms) de
aptitude
que usaremos relacionados con estos campos y otros
adicionales son los siguientes:
?essential
selecciona los paquetes marcados como esenciales?priority(
prioridad)
selecciona los paquetes con determinada prioridad (required
,important
,standard
,optional
oextra
)?automatic
selecciona los paquetes que se han instalado automáticamente?installed
selecciona los paquetes instalados (es lo mismo que~i
)?name(
regex)
selecciona los paquetes cuyo nombre case con la regex?section(
sección)
selecciona paquetes que pertenecen a la sección indicada (por ejemplolibs
)?architecture
selecciona los paquetes de determinada arquitectura (i386
,amd64
,all
,native
, ...)?not(
term)
,?and(
term1,
term2)
,?or(
term1,
term2)
negación, conjunción y disyunción lógicas de los terminos anteriores
Podéis encontrar más términos de búsqueda en la Search term reference de aptitude.
Es una buena práctica rodear siempre la expresión de búsqueda con "" para evitar que la shell interprete algunos caracteres especiales que usaremos.
Paquetes esenciales
Los paquetes marcados como Essential: yes
son absolutamente necesarios
para que el sistema funcione. Estarán siempre instalados en un sistema
sano (no roto) y las herramientas de gestión de paquetes se negarán a
desinstalarlos.
Averiguar cuáles son los paquetes marcados como esenciales es trivial:
aptitude search "?essential"
Pero, si se ha añadido una segunda arquitectura (como es mi caso con
i386
), aparecerán también los paquetes esenciales de esta otra
arquitectura. Para evitar este "ruido" en la salida seleccionaré sólo
los paquetes de la arquitectura nativa:
$ aptitude search "?essential ?architecture(native)"
i apt - commandline package manager
i base-files - Debian base system miscellaneous files
i base-passwd - Debian base system master password and gro
i bash - GNU Bourne Again SHell
i bsdutils - basic utilities from 4.4BSD-Lite
i coreutils - GNU core utilities
i dash - POSIX-compliant shell
i debianutils - Miscellaneous utilities specific to Debian
i diffutils - File comparison utilities
i dpkg - Debian package management system
i e2fsprogs - ext2/ext3/ext4 file system utilities
i findutils - utilities for finding files--find, xargs
i grep - GNU grep, egrep and fgrep
i gzip - GNU compression utilities
i hostname - utility to set/show the host name or domai
i A init - System-V-like init utilities - metapackage
i libc-bin - GNU C Library: Binaries
i login - system login tools
i mount - Tools for mounting and manipulating filesy
i ncurses-base - basic terminal type definitions
i ncurses-bin - terminal-related programs and man pages
i perl-base - minimal Perl system
i sed - The GNU sed stream editor
i sysvinit-utils - System-V-like utilities
i tar - GNU version of the tar archiving utility
i util-linux - Miscellaneous system utilities
En Debian "Jessie" hay 26 paquetes esenciales, 25 de ellos específicos
de la arquitectura (amd64
en mi caso) y uno (ncurses-base
) común a
todas las arquitecturas (all
).
Observad por favor que todos los paquetes esenciales están instalados2 (indicador 'i'). Si no fuera así tenéis un problema muy serio en vuestra instalación. También observad que hay un paquete esencial con el indicador 'A' de automáticamente instalado (volveremos sobre esto).
Paquetes por prioridad
Las diferentes prioridades que puede tener un paquete en Debian las podéis consultar en la FAQ (y más detalladamente en la Debian Policy), pero sirva esta breve descripción a modo de resumen (de mayor a menor prioridad):
required
: paquetes necesarios para el funcionamiento del sistema, incluyendo las herramientas básicas para repararlo. No deben borrarse.important
: paquetes (básicos) que uno espera encontrar en cualquier sistema Unix.standard
: paquetes estándar en cualquier sistema Linux, más herramientas para tener un sistema básico de consola.optional
: paquetes que posiblemente quieras instalar, aunque no sepas qué son, incluyendo el entorno gráfico y herramientas generales.extra
: paquetes que tienen conflictos con otros de más alta prioridad, o no caben enoptional
por diversas causas
Una instalación básica de Debian incluye normalmente los paquetes de prioridad
standard
o mayor.
Una regla importante de cara a qué prioridad debe tener un paquete es
que un paquete no debe depender de otro con una prioridad menor. No debe
haber paquetes de prioridad required
cuyas dependencias tengan
prioridad important
, por ejemplo.
Paquetes required
Los paquetes de prioridad required
y los paquetes esenciales parece
que se solapan. ¿Por qué tener un campo separado cuando podríamos
indicar lo mismo usando únicamente la prioridad? En realidad, no es así.
Para entenderlo veamos cuáles son los paquetes required
:
$ aptitude search "?priority(required) ?architecture(native)"
i base-files - Debian base system miscellaneous files
i base-passwd - Debian base system master password and gro
i bash - GNU Bourne Again SHell
i bsdutils - basic utilities from 4.4BSD-Lite
i coreutils - GNU core utilities
i dash - POSIX-compliant shell
i debconf - Debian configuration management system
i debconf-i18n - full internationalization support for debc
i debianutils - Miscellaneous utilities specific to Debian
i diffutils - File comparison utilities
i dpkg - Debian package management system
i e2fslibs - ext2/ext3/ext4 file system libraries
i e2fsprogs - ext2/ext3/ext4 file system utilities
i findutils - utilities for finding files--find, xargs
p gcc-4.8-base - GCC, the GNU Compiler Collection (base pac
i A gcc-4.9-base - GCC, the GNU Compiler Collection (base pac
i grep - GNU grep, egrep and fgrep
i gzip - GNU compression utilities
i hostname - utility to set/show the host name or domai
i A init - System-V-like init utilities - metapackage
i initscripts - scripts for initializing and shutting down
i libacl1 - Access control list shared library
i libattr1 - Extended attribute shared library
i libblkid1 - block device id library
i libc-bin - GNU C Library: Binaries
i libc6 - GNU C Library: Shared libraries
i libcomerr2 - common error description library
i libgcc1 - GCC support library
i liblocale-gettext-perl - module using libc functions for internatio
i A liblzma5 - XZ-format compression library
i A libmount1 - device mounting library
i libncurses5 - shared libraries for terminal handling
i libpam-modules - Pluggable Authentication Modules for PAM
i A libpam-modules-bin - Pluggable Authentication Modules for PAM -
i libpam-runtime - Runtime support for the PAM library
i libpam0g - Pluggable Authentication Modules library
i libpcre3 - Perl 5 Compatible Regular Expression Libra
i libselinux1 - SELinux runtime shared libraries
i libsepol1 - SELinux library for manipulating binary se
i A libsmartcols1 - smart column output alignment library
i libss2 - command-line interface parsing library
i libtext-charwidth-perl - get display widths of characters on the te
i libtext-iconv-perl - converts between character sets in Perl
i libtext-wrapi18n-perl - internationalized substitute of Text::Wrap
i A libtinfo5 - shared low-level terminfo library for term
i libuuid1 - Universally Unique ID library
i login - system login tools
i lsb-base - Linux Standard Base 4.1 init script functi
i mawk - a pattern scanning and text processing lan
i mount - Tools for mounting and manipulating filesy
i A multiarch-support - Transitional package to ensure multiarch c
i ncurses-base - basic terminal type definitions
i ncurses-bin - terminal-related programs and man pages
i passwd - change and administer password and group d
i perl-base - minimal Perl system
i sed - The GNU sed stream editor
i sensible-utils - Utilities for sensible alternative selecti
i A startpar - run processes in parallel and multiplex th
i sysv-rc - System-V-like runlevel change mechanism
i sysvinit-utils - System-V-like utilities
i tar - GNU version of the tar archiving utility
i tzdata - time zone and daylight-saving time data
i util-linux - Miscellaneous system utilities
i zlib1g - compression library - runtime
En Jessie hay 64 paquetes required
, 55 específicos de la arquitectura
más 9 independientes de la arquitectura (arquitectura all
). De ellos,
25 son paquetes esenciales, y los otros 39 no. Es decir, hay paquetes
required
que no tienen el indicador de Essential:
activado, y por lo
tanto el gestor de paquetes no previene que se borren. De hecho, ¡tengo
un paquete required
no instalado!
$ aptitude search "?priority(required) ?architecture(native) ?not(?installed)"
p gcc-4.8-base - GCC, the GNU Compiler Collection (base pac
Tranquilos todos. Ese paquete no está instalado porque yo lo he borrado
manualmente cuando me deshice de todos los paquetes de gcc 4.8, puesto
que ya tenía los de gcc 4.93. Pero el caso es que me sirve para
ilustrar con un ejemplo las razones de la distinción de Essential
y
required
: los paquetes esenciales no se pueden borrar en ningún caso
mientras que los required
sí (por ejemplo porque se proporcione una
alternativa). Otro motivo es que dos paquetes con conflictos
(excluyentes) no pueden estar ambos marcados como esenciales (tendrían
que estar ambos instalados, algo que es obviamente imposible) mientras
que sí podrían pertenecer ambos a required
, siempre que sólo uno de
ellos esté instalado.
Así que los paquetes que forman parte de required
son aquellos
marcados como Essential
más sus dependencias, con la
particularidad de que estas dependencias deben poder ser sustituidas por
otros paquetes diferentes, lo que les impide ser Essential
ellas
mismas. Estas dependencias cambiantes provienen de programas con
alternativas (como mawk
, que puedes sustituirlo por gawk
o por
cualquier otro awk) o de software del cual puedes tener instaladas
varias versiones a la vez (gcc-4.8-base / gcc-4.9-base/ futuros
gcc-X.Y-base). Así nos encontramos con cosas tan aparentemente
contraintuitivas como que libc6
, el paquete del cual dependen
prácticamente todos los demás, no sea Essential
. Esta
"particularidad" es sin embargo la que permite instalar una biblioteca C
estándar diferente (como las que usan otras arquitecturas Debian) o
incluso una hipotética futura libc7, manteniendo abierta la posibilidad
de que los que quieran sigan usando la libc6 actual.
En resumen, que un paquete tenga una prioridad required
no obliga a
que esté instalado (aunque sí es una fuerte indicación de que debería
estarlo, salvo que realmente sepas lo que estás haciendo). Por otro
lado, para indicar al gestor de paquetes que es obligatorio que cierto
paquete esté instalado debemos construirlo con su indicador Essential
a yes
—y lidiar con las consecuencias y restricciones de tal
decisión.
Paquetes important
Si habéis sido observadores os habréis fijado que hay un paquete
Essential
que no está entre los que tienen prioridad required
(sólo
había 25 de los 26 Essential
en required
):
$ aptitude search "?essential ?not(?priority(required)) ?architecture(native)"
i apt - commandline package manager
$ aptitude show apt
Package: apt
Essential: yes
State: installed
Automatically installed: no
Version: 1.0.9.8
Priority: important
Section: admin
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Uncompressed Size: 3879 k
Depends: libapt-pkg4.12 (>= 1.0.9.8), libc6 (>= 2.15), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.9), debian-archive-keyring, gnupg
Suggests: aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), apt-doc, python-apt
...
No conozco la razón exacta por la que apt
tiene prioridad important
en vez de required
, pero puedo apostar sin arriesgar mucho a que tiene
que ver con sus dependencias. Concretamente, al hecho de depender de la
biblioteca estándar de C++ (al estar apt
escrita en ese lenguaje de
programación), que hubiera obligado a mover la libstdc++
también a
required
(para disgusto de unos pocos), junto con gnupg
y el resto
de dependencias no required
. Además, históricamente apt
ha tenido la
consideración de herramienta adicional para facilitar el uso de dpkg
,
que por entonces era el único y verdadero gestor de paquetes, y de hecho
todavía se puede usar exclusivamente dpkg
4 para instalar y
desinstalar paquetes. Aunque ¿quién en su sano juicio querría hacer eso
hoy en día?
Echemos un vistazo a la lista de paquetes de prioridad important
:
$ aptitude search "?priority(important) ?architecture(native)"
i adduser - add and remove users and groups
i apt - commandline package manager
i apt-utils - package management related utility program
i bsdmainutils - collection of more utilities from FreeBSD
i cpio - GNU cpio -- a program to manage archives o
i cron - process scheduling daemon
i debian-archive-keyring - GnuPG archive keys of the Debian archive
i dmidecode - SMBIOS/DMI table decoder
i gnupg - GNU privacy guard - a free PGP replacement
i gpgv - GNU privacy guard - signature verification
i groff-base - GNU troff text-formatting system (base sys
i ifupdown - high level tools to configure network inte
i A init-system-helpers - helper tools for all init systems
i A iproute2 - networking and traffic control tools
i iptables - administration tools for packet filtering
i iputils-ping - Tools to test the reachability of network
i isc-dhcp-client - DHCP client for automatically obtaining an
i isc-dhcp-common - common files used by all of the isc-dhcp p
i A kmod - tools for managing Linux kernel modules
i less - pager program similar to more
i A libapt-inst1.5 - deb package format runtime library
i A libapt-pkg4.12 - package management runtime library
i A libboost-iostreams1.55.0- Boost.Iostreams Library
i libbz2-1.0 - high-quality block-sorting file compressor
i A libestr0 - Helper functions for handling strings (lib
i libgdbm3 - GNU dbm database routines (runtime version
i A libjson-c2 - JSON manipulation library - shared library
i A libkmod2 - libkmod shared library
i A liblogging-stdlog0 - easy to use and lightweight logging librar
i A liblognorm1 - Log normalizing library
i libncursesw5 - shared libraries for terminal handling (wi
i libnewt0.52 - Not Erik's Windowing Toolkit - text mode w
i A libpipeline1 - pipeline manipulation library
i libpopt0 - lib for parsing cmdline parameters
i A libprocps3 - library for accessing process information
i libreadline6 - GNU readline and history libraries, run-ti
i libsigc++-2.0-0c2a - type-safe Signal Framework for C++ - runti
i libslang2 - S-Lang programming library - runtime versi
i A libssl1.0.0 - Secure Sockets Layer toolkit - shared libr
i libstdc++6 - GNU Standard C++ Library v3
i A libudev1 - libudev shared library
i libusb-0.1-4 - userspace USB programming library
i A libxtables10 - netfilter xtables library
i logrotate - Log rotation utility
i man-db - on-line manual pager
i manpages - Manual pages about using a GNU/Linux syste
i nano - small, friendly text editor inspired by Pi
i net-tools - NET-3 networking toolkit
i netbase - Basic TCP/IP networking system
i netcat-traditional - TCP/IP swiss army knife
p nfacct - netfilter accounting object tool
i procps - /proc file system utilities
i readline-common - GNU readline and history libraries, common
i rsyslog - reliable system and kernel logging daemon
i A systemd - system and service manager
i A systemd-sysv - system and service manager - SysV links
i tasksel - tool for selecting tasks for installation
i tasksel-data - official tasks used for installation of De
i traceroute - Traces the route taken by packets over an
i udev - /dev/ and hotplug management daemon
i vim-common - Vi IMproved - Common files
p vim-tiny - Vi IMproved - enhanced vi editor - compact
i wget - retrieves files from the web
i whiptail - Displays user-friendly dialog boxes from s
En Debian Jessie hay 64 paquetes important
, 56 específicos de la
arquitectura más 8 independientes de la arquitectura (all
). Y, como he
dicho, sólo apt es Essential
, y por lo tanto obligatorio tenerlo
instalado (más sus dependencias). El resto, aunque sea poco
recomendable, el sistema de paquetes nos permite eliminarlos, y de hecho
en mi caso podéis ver que tengo un un par de paquetes important
desinstalados5.
Paquetes standard
Debian Jessie cuenta con 103 paquetes marcados con prioridad standard
,
divididos en 83 dependientes y 20 independientes de arquitectura. No voy
a incluir la lista completa porque este artículo empieza a ser
enormemente largo (y para estas alturas ya deberíais saber hacerlo
vosotros mismos) pero sí diré que entre ellos se encuentran cosas que
considero bastante básicas como at, file, info, time, telnet, ftp, el
cliente de OpenSSH, patch, locales o bzip2, los intérpretes de perl y
python (2.7), y luego cosas que me resulta más discutibles considerarlas
básicas, como un servidor SMTP (exim4), un par de clientes de correo
(mailx y mutt), m4, procmail, whois, el diccionario wamerican e incluso
el propio aptitude. Además 45 de estos 103 paquetes son bibliotecas
dinámicas que implementan funciones bastante básicas para el sistema: de
seguridad, de red, de almacenamiento de datos, autenticación,
criptografía, ... Otros paquetes de prioridad standard
enlazan con
estas bibliotecas, y por eso están aquí.
Tampoco tengo instalados la totalidad de los paquetes de prioridad
standard
. En concreto no tengo instalados 11 paquetes, de los cuales 8
son bibliotecas dinámicas (sobre todo relacionadas con el sistema de
autenticación Kerberos), dos más son paquetes perl (?), y el último es
un paquete "dummy" de transición que sólo existe para asegurarse que al
actualizar la distribución el nuevo bind9-host
se instala si teníamos
instalado el antiguo host
.
Paquetes optional
y extra
Si bien los paquetes de alta prioridad (que sumados son 231 paquetes)
son los que permiten tener la distribución Debian funcionando
mínimamente, el grueso de la distribución la forman los paquetes con
prioridad optional
(31.102 paquetes) y extra
(11.669 paquetes),
hasta llegar a los 42.996 paquetes nativos que hay en total6. Son los
paquetes con estas prioridades sobre los que voy a trabajar, ya que si
algo fuera mal al menos tengo la certeza de que el sistema no va a
quedar inusable (al menos no para los que estamos acostumbrados a
manejarnos en la línea de comandos).
Paquetes automáticamente instalados
Previamente hemos visto en algunos de los listados de paquetes el
indicador 'A', que significa que dicho paquete ha sido instalado
automáticamente. Dicho indicador es una información que apt-get
o
aptitude
añade a la base de datos de paquetes instalados cuando un
paquete es instalado no porque sea solicitado por el usuario, sino
porque la propia herramienta decide instalarlo para resolver una
dependencia. El objeto de guardar esta información es desinstalar
automáticamente estos paquetes 'A' cuando desinstalamos el paquete o los
paquetes que provocaron la instalación por dependencia. De esta forma,
mantenemos la distribución libre de paquetes innecesarios.
Desgraciadamente, esto es sólo la teoría. En la práctica, ha habido una serie de bugs que hacían que en algunas circunstancias esta información desapareciera, lo que significaba que cuando posteriormente desinstalábamos los paquetes, sus dependencias no se desinstalaran y permanecieran en el sistema a pesar de no ser requeridos por ningún otro paquete. Actualmente parece que todos esos bugs han sido corregidos, pero si lleváis como yo mucho tiempo con la misma distribución Debian, pasando de versión en versión, es muy posible que tengáis paquetes que en un momento dado hayan perdido su indicador 'A' y permanezcan innecesariamente instalados en vuestro sistema por esta causa. Esto se da especialmente con paquetes de bibliotecas dinámicas.
Hay varios motivos por lo que no es deseable tener paquetes instalados que en realidad no se usan. El principal motivo es que como todo software tiene bugs aún por descubrir, cuanto más software tenemos instalado más bugs tenemos en nuestro sistema, esperando el momento adecuado para fastidiarnos. Y esto es especialmente importante cuando un porcentaje de esos bugs son bugs de seguridad. Reducir la cantidad de sofware instalado significa reducir lo que se llama la "superficie de ataque", por lo que tener software en nuestro sistema cuando en realidad no lo necesitamos es siempre una mala idea. Además, siempre supone una ocupación de recursos adicional, que si bien la ocupación de disco hoy en día suele ser despreciable, no lo es tanto cuando tenemos en cuenta que esos paquetes también se actualizan por la red y por lo tanto consumen ancho de banda (tanto nuestro ancho de banda como el de los repositorios de Debian), y también se tienen que computar una y otra vez a la hora de resolver dependencias. Un montón de ciclos de procesador y de bits movidos por la red innecesario y que no aporta nada.
Entrando en faena
Todo esto ha sido una larga explicación para lo que luego van a ser unos pocos comandos, pero he creído que es importante conocer el contexto. No me gustan las "recetas" que sueltan los comandos sin más para que se ejecuten "mágicamente". Basta que algún detalle haya cambiado o el entorno donde se ejecuten los comandos no sea exactamente el mismo para que la "solución" se convierta en un problema aun mayor.
De todas formas, a pesar de que las operaciones que voy a utilizar no las considero peligrosas, voy a hacer el habitual disclaimer y a decir eso de úsalas bajo tu propia responsabilidad. Probablemente la gran mayoría de los que estéis leyendo esta enorme pared de texto sabéis perfectamente lo que hacéis y no necesitaba decirlo, pero uno nunca sabe quién va a terminar leyendo esto y qué tipo de FrankenDebian tendrá7.
Ya he dicho previamente que, para minimizar riesgos, sólo voy a jugar
con paquetes con prioridades bajas optional
o extra
de forma que lo
peor que pueda pasar es que desinstalemos algo de lo que dependa el
sistema gráfico. Así que empezaré echando un vistazo a los paquetes
NO automáticamente instalados que tenemos en esas dos prioridades:
aptitude search "?or(?priority(optional),?priority(extra)) ?installed ?not(?automatic)"
La lista obtenida os tiene que resultar muy familiar, porque son
—o mejor dicho deberían ser— los paquetes que habéis ido
instalando manualmente a lo largo del tiempo. Si en esa lista hay muchos
nombres que no os suenan, sobre todo de bibliotecas dinámicas lib*
, es
que es muy posible que durante un tiempo hayáis sido victimas de los
bugs que hacen desaparecer el indicador automatic de automáticamente
instalado (aunque ya haya sido corregido).
Por fortuna, la pérdida del indicador automatic es fácilmente
subsanable. Si estáis positivamente seguros que un paquete se instaló
automáticamente por dependencias de otro, y queréis que recupere el
indicador 'A' de automáticamente instalado, aptitude
nos permite
hacerlo mediante markauto
:
aptitude markauto un-paquete otro-paquete mas-paquetes ...
Mucho cuidado con marcar como automático un paquete que no tenga otro
que dependa de él, o en la próxima operación sobre paquetes aptitude
(o apt-get
) intentará borrarlo "porque ya no es necesario".
Sin embargo, revisar los paquetes uno a uno y marcarlos como
automáticamente instalados no es algo práctico, salvo que la lista sea
muy reducida. Necesitamos un método rápido para obtener qué paquetes nos
interesa marcar como automáticamente instalados. Por ejemplo, si
pudiéramos seleccionar todas esas bibliotecas dinámicas... Pues bien, sí
que podemos, usando el término de selección ?section
:
aptitude search "?or(?priority(optional),?priority(extra)) ?installed ?not(?automatic) ?section(libs)"
Este comando nos listará todas las bibliotecas dinámicas (paquetes de la
sección libs) con prioridad optional
o extra
que estén instaladas,
pero que no estén marcadas como instaladas automáticamente. Justo lo que
estábamos buscando. Y lo realmente interesante es que aptitude
nos
permite usar la misma expresión para marcar todas como 'A' a la vez, sin
tener que hacerlo paquete por paquete.
Pero como este marcado masivo es la operación peligrosa (si marcamos lo que no debemos), antes de hacerlo nos debemos preguntar: ¿es realmente seguro marcar todas las bibliotecas dinámicas como instaladas automáticamente? En general, sí: las bibliotecas dinámicas no tienen entidad por sí mismas, sólo funcionan cuando son enlazadas desde un ejecutable, lo que nos debería garantizar que existe una dependencia del paquete del ejecutable al de la biblioteca dinámica. Sin embargo, hay algunas excepciones a tener en cuenta. Si ejecuto el comando anterior en mi sistema (que ya ha pasado por este proceso), me devuelve:
$ aptitude search "?or(?priority(optional),?priority(extra)) ?installed ?not(?automatic) ?section(libs)"
i gstreamer0.10-plugins-ugly - Complementos de GStreamer del conjunto «ugly»
i gstreamer1.0-libav - libav plugin for GStreamer
i libdvdcss2 - library designed for accessing DVDs
Como veis, aún tengo tres bibliotecas dinámicas instaladas "manualmente", y las tengo así intencionadamente. Las dos primeras las instalé para solucionar mis problemas con tumbler, y la última es una biblioteca compilada a mano. El caso es que no quiero que ninguna de estas tres bibliotecas dinámicas se desinstalen automáticamente aunque en un momento dado no tengan aparentes dependencias. En el caso de las dos primeras, el problema es que hay una dependencia de funcionalidad no expresada en el grafo de dependencias de Debian (si están disponibles, tumbler usa estas bibliotecas para mostrar el icono de ciertos tipos de videos, si no usa un icono genérico), y en la tercera porque no está en los repositorios (así que, si me la borrara, la tendría que recrear a mano).
No es casualidad que las tres bibliotecas sean "problemáticas de distribuir" por asuntos legales (patentes, etc). Esto hace que programas que en otra situación tendrían una dependencia directa, las usen indirecta u opcionalmente, tratando de evitar dependencias de paquetes que pueden no estar disponibles.
El caso es que podéis encontraros con la misma situación que yo, que
ciertas bibliotecas como las mencionadas no sea buena idea tenerlas como
automáticamente instaladas para que el gestor de paquetes no trate de
eliminarlas por su cuenta, pese a ser necesarias para que ciertas
características (¡como la reproducción de videos MPEG4!) funcionen. Así
que no nos queda otra línea de acción que primero marcar todas como 'A'
e inmediatamente a continuación "desmarcar" la 'A' de las excepciones
usando aptitude unmarkauto
.
Así que, resumiendo:
- marcar todas las bibliotecas dinámicas como automáticas con markauto
- desmarcar con unmarkauto las bibliotecas "problemáticas" (como
las
-plugin-bad
,-plugins-ugly
,-libav
y-ffmpeg
de gstreamer). - invocar
aptitude install
para que aptitude haga lo que tenga que hacer y desinstale lo que ya no se use y esté marcado como automáticamente instalado
Lo que se traduce en los comandos:
$ aptitude markauto "?or(?priority(optional),?priority(extra)) ?installed ?not(?automatic) ?section(libs)"
$ aptitude unmarkauto gstreamer0.10-plugins-ugly gstreamer0.10-plugins-bad gstreamer1.0-libav ...
# aptitude install
Y ahora, si todo hay ido bien, aptitude
querrá desinstalar un puñado
de bibliotecas dinámicas innecesarias.
Problemas: si la lista de paquetes a eliminar resultara ser monstruosamente grande, y sobre todo si hay en ella paquetes que sabes que no deberían borrarse, aun te queda la posibilidad de abortar la operación. Por desgracia, no se puede volver a la situación anterior a la del markauto, por lo que deberás averiguar qué paquetes no deberías haber marcado como automáticos y hacerles un "unmarkauto". O, como solución de última instancia, hacer un unmarkauto masivo usando la misma expresión (pero perderías la 'A' de absolutamente todas las bibliotecas de las prioridades seleccionadas).
De todas formas, lo normal es que todo haya ido bien y las bibliotecas
dinámicas habrán sido todas marcadas como automáticas y eliminadas las
no usadas. Haciendo una nueva búsqueda con aptitude search
no deberían
aparecer más bibliotecas que aquellas que hayas preservado con
unmarkauto.
Tras la limpieza de bibliotecas, la lista de paquetes instalados (excluyendo la sección de bibliotecas dinámicas que ya ha sido tratada) sin indicador 'A' debería aproximarse mucho a los paquetes que hemos ido instalando manualmente en el sistema durante su vida:
aptitude search "?or(?priority(optional),?priority(extra)) ?installed ?not(?automatic) ?not(?section(libs))"
Si no es así, lo que nos queda es trabajo manual: averiguar cuáles
tienen pinta de haber sido instalados por otros paquetes (aptitude why
puede ayudar aquí) y marcarlos con markauto. También podemos aprovechar
y extender la limpieza a esos paquetes que instalamos manualmente y ya
no usamos, o que ni nos acordábamos que estaban ahí.
¿Aplicar sobre prioridades altas?
Si habéis tenido éxito, tal vez estéis sopesando si no deberíais hacer
lo mismo sobre los paquetes de prioridad más alta (required
,
important
y standard
). Mi respuesta es que, dado el pequeño número
de paquetes en estas prioridades, y su importancia, en general no creo
que merezca la pena. Personalmente, lo he aplicado sobre los paquetes de
prioridad estandard
, pero sólo despues de comprobar exhaustivamente
que no iba a romper nada. Mucho trabajo para librarse de ¿7? paquetes.
Sin embargo, tampoco es algo a desestimar a la ligera: al ser paquetes muy frecuentemente instalados, son candidatos ideales para utilizar sus vulnerabilidades en exploits y ataques. Cada paquete desinstalado de este tipo ayuda a reducir significativamente la superficie de ataque del sistema, lo cual puede hacer merecer la pena el esfuerzo adicional de investigación.
¿Y deborphan?
Algunos os estaréis preguntando por que no he utilizado
deborphan, que es precisamente una herramienta para buscar
paquetes huérfanos sin dependencias, en vez de montar todo este
tinglado. Primero, porque deborphan usa un heurístico8 muy similar al
que hemos utilizado aquí mediante aptitude search
, pero que opera
sobre todos los paquetes sin importar su prioridad. Por defecto,
deborphan también busca paquetes instalados de las secciones libs (y
oldlibs) sin dependencias hacia ellos. De hecho, los paquetes devueltos
por deborphan y los devueltos por la expresión de aptitude que hemos
utilizado deberían ser los mismos, si exceptuamos que deborphan mostrará
tambien los de prioridad required
, important
y standard
(y la
sección oldlibs), algo que ya he explicado que yo no quería por
considerar que aumentaba las probabilidades de una pifia.
Segundo, porque deborphan en realidad sólo sugiere paquetes a borrar, pero no los borra ni marca ni nada. Usar aptitude nos ha permitido no sólo mostrar paquetes sino aplicar operaciones sobre ellos sin tener que ir uno a uno.
Y tercero, y lo más importante: porque aprendiendo a usar herramientas
generales nos permite hacer muchas más cosas que las que nos permiten
hacer herramientas específicas. ¿Que quisieramos por ejemplo marcar como
automáticamente instalados todos los paquetes cuyo nombre termina en
-common
? Fácil, sólo tenemos que ampliar nuestro repertorio con el
término de búsqueda ?name()
y usar una sencilla expresión regular.
Por supuesto, así como todo gran poder conlleva una gran responsabilidad, toda herramienta potente conlleva una gran potencia de fuego contra nuestras extremidades inferiores. Lo que significa que es importante conocer el sistema y saber lo que se está haciendo, por si algo saliera mal.
:wq
-
aunque no lo indique, todos los comandos los he prefijado con
LANG=C
para que la salida por pantalla sea siempre la misma independiementemente del idioma configurado ↩ -
esta regla de los paquetes esenciales sólo se aplica a los paquetes de la arquitectura nativa, para el resto de arquitecturas los paquetes esenciales no tienen por qué estar instalados —y de hecho no lo están— ↩
-
la razón de poder instalar varias versiones del mismo compilador da para su propio artículo ↩
-
y lapiz y papel, para anotar qué paquetes —las dependencias— tenías que instalar antes que cuáles ↩
-
tengo la versión completa de vim instalada, así que
vim-tiny
es superfluo; y en cuanto anfacct
no parece que me haya hecho falta hasta ahora ↩ -
no os salen las cuentas por esto:
aptitude search "?and(?priority(optional),?priority(extra)) ?architecture(native)"
(es evidente que esos paquetes están mal construidos) ↩ -
al fin y al cabo de lo único que podemos estar realmente seguros es de la muerte y de los impuestos ↩
-
ese es el heurístico por defecto, pero tiene otros, ver
man deborphan
para más detalles ↩