O pacote Debian não é apenas um arquivamento de arquivos prontos para serem instalados. Ele é parte de um todo, e descreve sua relação com outros pacotes Debian (dependências, conflitos, sugestões). Ele também fornece scripts que habilitam a execução de comandos em diferentes estágios do ciclo de vida do pacote (instalação, remoção, atualizações). Estes dados são usados pelas ferramentas de gerencia de pacotes mas não são parte do programa empacotado, eles são, junto com o pacote, o que chamamos de sua “meta-informação” (informação sobre outras informações).
5.2.1. Descrição: O arquivo control
This file uses a structure similar to email headers (as defined by RFC 2822). For example, for apt, the control
file looks like the following:
$
apt-cache show apt
Package: apt
Version: 1.0.9.6
Installed-Size: 3788
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Replaces: manpages-it (<< 2.80-4~), manpages-pl (<< 20060617-3~), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~), sun-java5-jdk (>> 0), sun-java6-jdk (>> 0)
Depends: libapt-pkg4.12 (>= 1.0.9.6), 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
Conflicts: python-apt (<< 0.7.93.2~)
Breaks: manpages-it (<< 2.80-4~), manpages-pl (<< 20060617-3~), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~), sun-java5-jdk (>> 0), sun-java6-jdk (>> 0)
Description-pt_BR: gerenciador de pacotes em linha de comando
Este pacote fornece ferramentas em linha de comando para busca e
gerenciamento assim como consultas de informações sobre pacotes como um
acesso de baixo nível a todas as funcionalidades da biblioteca libapt-pkg.
.
Inclui:
* apt-get para obter pacotes e informações sobre os mesmos de fontes
autenticadas e para instalação, atualização e remoção de pacotes e
dependências
* apt-cache para consultar informações disponíveis sobre pacotes
instalados e instaláveis
* apt-cdrom para usar mídias removíveis como fontes de pacotes
* apt-config como uma interface para as configurações
* apt-key para uma interface para as chaves de autenticação
Description-md5: 9fb97a88cb7383934ef963352b53b4a7
Tag: admin::package-management, devel::lang:ruby, hardware::storage,
hardware::storage:cd, implemented-in::c++, implemented-in::perl,
implemented-in::ruby, interface::commandline, network::client,
protocol::ftp, protocol::http, protocol::ipv6, role::program,
role::shared-lib, scope::application, scope::utility, sound::player,
suite::debian, use::downloading, use::organizing, use::searching,
works-with::audio, works-with::software:package, works-with::text
Section: admin
Priority: important
Filename: pool/main/a/apt/apt_1.0.9.6_amd64.deb
Size: 1107560
MD5sum: a325ccb14e69fef2c50da54e035a4df4
SHA1: 635d09fcb600ec12810e3136d51e696bcfa636a6
SHA256: 371a559ce741394b59dbc6460470a9399be5245356a9183bbeea0f89ecaabb03
5.2.1.1. Dependências: o campo Depends
(depende de)
As dependências são definidas no campo Depends
no cabeçalho do pacote. Este campo é uma lista de condições a serem satisfeitas para o pacote funcionar corretamente — Esta informação é usada por ferramentas como o apt
para instalar as biblitecas necessárias, nas versões corretas, preenchendo as dependências do pacote a ser instalado. Para cada dependência é possível restringir o intervalo de versões que satisfazem esta condição. Em outras palavras, é possível expressar o fato de que nós precisamos do pacote libc6 em uma versão igual ou superior a “2.15” (escreve-se “libc6 (>= 2.15)
”). Operadores de comparação de versão são os seguintes:
Numa lista de condições para serem satisfeitas, a vírgula serve como um separador. Ela deve ser interpretada como um "e" lógico. Em condicionais, a barra vertical ("|") expressa um "ou" lógico (é um "ou" inclusivo, não um "ou isto ou aquilo"). Tem prioridade sobre o "e", pode ser usado tanto quanto necessário. Portanto, a dependência "(A ou B) e C" é escrita como
A | B, C
. Por outro lado, a expressão "A ou (B e C)" deve ser escrita como "(A ou B) e (A ou C)", uma vez que o campo
Depends
não aceita parêntesis que mudem a ordem de prioridades entre os operadores lógicos "ou" e "e". Ele poderia ser escrito, portanto, como
A | B, A | C
.
O sistema de dependências é um bom mecanismo para garantir a operação de um programa, mas ele tem outro uso com os "meta-pacotes". Estes são pacotes vazios que apenas descrevem dependências. Eles facilitam a instalação de um grupo consistente de programas pré-selecionados pelo mantenedor do meta-pacote; assim, apt install meta-package
vai instalar automaticamente todos os programas nas dependências do meta-pacote. Os pacotes gnome, kde-full e linux-image-amd64 são exemplos de meta-pacotes.
5.2.1.2. Conflicts: o campo Conflicts
O campo Conflicts
indica quando um pacote não pode ser instalado simultaneamente com outro. As razões mais comuns para isto é que ambos os pacotes incluem um arquivo de mesmo nome, ou fornecem o mesmo serviço na mesma porta TCP, ou vão atrapalhar a operação um do outro.
O dpkg
vai se recusar a instalar um pacote se ele iniciar um conflito com um pacote já instalado, a menos que o novo pacote especifique que ele "substitui" o pacote instalado, e neste caso o dpkg
vai escolher substituir o pacote antigo pelo novo. O apt
sempre vai seguir suas instruções: se você escolher instalar um novo pacote, ele vai automaticamente se oferecer para desinstalar o pacote que apresentar um problema.
5.2.1.3. Incompatibilidades: o campo Breaks
O campo Breaks
tem um efeito similar ao do campo Conflicts
, mas com um significado especial. Ele assinala que a instalação de um pacote vai "quebrar" outro pacote (ou versões específicas dele). Em geral, esta incompatibilidade entre dois pacotes é transitória, e a relação Breaks
se refere especificamente a estas versões incompatíveis.
O dpkg
vai se recusar a instalar um pacote que quebra um pacote já instalado, e o apt
vai tentar resolver o problema atualizando o pacote que vai ser quebrado para uma nova versão (que se espera que tenha sido corrigida, logo, voltou a ser compatível).
Este tipo de situação pode ocorrer no caso de atualizações sem retrocompatibilidade: este é o caso se a nova versão não funciona mais com a versão antiga, e causa um mal funcionamento em outro programa sem fazer "provisões especiais". O campo Breaks
evita que o usuário se ponha nestes tipos de problemas.
5.2.1.4. Itens fornecidos: o campo Provides
Este campo introduz o interessante conceito de "pacote virtual". Ele tem muitos papéis, mas dois são de especial importância. O primeiro consiste em usar um pacote virtual para associar um serviço genérico com ele (o pacote "fornece" o serviço). O segundo indica que um pacote substitui completamente o outro, e que para este propósito ele também pode satisfazer as dependências que o outro satisfaz. É também possível criar um pacote de substituição sem ter que usar o mesmo nome de pacote.
5.2.1.4.1. Fornecendo um “Serviço”
Vamos discutir o primeiro caso em maiores detalhes com um exemplo: Dizemos que todos os servidores de e-mail, como o postfix ou o sendmail "fornecem" o pacote virtual mail-transport-agent. Então, qualquer pacote que precise deste serviço para ser funcional (e.g. um gerenciador de lista de e-mail, como o smartlist ou o sympa) simplesmente afirma nas suas dependências que ele precisa de um mail-transport-agent ao invés de especificar uma grande porém incompleta lista de possíveis soluções (e.g. postfix | sendmail | exim4 | …
). Além disso, é inútil instalar dois servidores de e-mail na mesma máquina, sendo por isso que cada um destes pacotes declara um conflito com o pacote virtual mail-transport-agent. Um conflito entre um pacote e ele próprio é ignorado pelo sistema, mas esta técnica irá proibir a instalação de dois servidores de e-mail lado a lado.
5.2.1.4.2. "Interchangeability" com outro pacote
O campo Provides
é também interessante quando o conteúdo de um pacote é incluído em um pacote maior. Por exemplo, o módulo Perl libdigest-md5-perl era um módulo opcional no Perl 5.6, e foi integrado como padrão no Perl 5.8 (e versões posteriores, como a 5.20 presente no Jessie). Desta forma, o pacote perl tem, desde a versão 5.8, declarado Provides: libdigest-md5-perl
de forma que as dependências neste pacote são satisfeitas se o usuário tem o Perl 5.8 (ou mais recentes). O pacote libdigest-md5-perl será eventualmente removido, uma vez que ele não terá utilidade quando versões antigas do Perl forem removidas.
Esta funcionalidade é muito útil, já que nunca é possível antecipar os caprichos do desenvolvimento, e é preciso poder se renomear, e fazer outras substituições automáticas, de software obsoleto.
5.2.1.4.3. Limitações Antigas
Virtual packages used to suffer from some limitations, the most significant of which was the absence of a version number. To return to the previous example, a dependency such as Depends: libdigest-md5-perl (>= 1.6)
, despite the presence of Perl 5.10, would never be considered as satisfied by the packaging system — while in fact it most likely is satisfied. Unaware of this, the package system chose the least risky option, assuming that the versions do not match.
This limitation has been lifted in dpkg 1.17.11, and is no longer relevant in Jessie. Packages can assign a version to the virtual packages they provide with a dependency such as Provides: libdigest-md5-perl (= 1.8)
.
5.2.1.5. Substituindo arquivos: o campo Replaces
O campo Replaces
indica que o pacote contém arquivos que também estão presentes em outros pacotes, mas que o pacote foi designado legitimamente para substituí-los. Sem esta especificação, o dpkg
falha, dizendo que não pode sobreescrever arquivos de outro pacote (tecnicamente, é possível força-lo a tal com a opção --force-overwrite
, mas isso não é considerado uma operação padrão). Isto permite a identificação de problemas potenciais e requer que o mantenedor estude o assunto antes de escolher se adiciona tal campo.
O uso deste campo é justificado quando os nomes dos pacotes mudam ou quando um pacote é incluído em outro. Também acontece quando o mantenedor decide distribuir arquivos diferentes entre vários pacotes binários produzidos a partir do mesmo fonte: um arquivo substituído não pertence mais ao pacote antigo, mas apenas ao novo.
Se todos os arquivos num pacote instalado foram substituídos, o pacote é considerado "a ser removido". Finalmente, este campo também encoraja o dpkg
a remover o pacote substituido onde existir conflito.
5.2.2. Scripts de Configuração
Além do arquivo control
, o arquivamento control.tar.gz
para cada pacote Debian pode conter vários scripts, chamados pelo dpkg
em diferentes estágios do processamento de um pacote. A política Debian descreve os possíveis casos em detalhes, especificando os scripts e os argumentos que eles recebem. Estas sequências podem se complicadas, já que se um dos scripts falha, o dpkg
vai tentar retornar a um estado satisfatório cancelando a instalação ou a remoção em andamento (na medida do possível).
Em geral, o script preinst
é executado antes da instalação do pacote, enquanto que o postinst
é logo depois. Da mesma forma, o prerm
é chamado antes da remoção de um pacote e o postrm
depois. Uma atualização de um pacote é equivalente à remoção da versão anterior e a instalação do novo. Não é possível descrever em detalhes todos os cenários possíveis aqui, mas vamos discutir os dois mais comuns: uma instalação/atualização e uma remoção.
5.2.2.1. Instalação e upgrade (atualização)
Aqui está o que acontece durante uma instalação (ou uma atualização):
Para uma atualização ("update"), o dpkg
chama o old-prerm upgrade new-version
.
Ainda para uma atualização, o dpkg
então executa new-preinst upgrade old-version
; para uma primeira instalação, ele executa new-preinst install
. Ele pode adicionar a versão antiga no último parâmetro, se o pacote já foi instalado e removido "since" (mas não "purged", os arquivos de configuração foram "retained").
Os arquivos do novo pacote são então desempacotados, se algum arquivo já existe, ele é substituído, mas uma cópia de backup é temporariamente feita.
Para uma atualização, o dpkg
executa old-postrm upgrade new-version
.
dpkg
atualiza todos os dados internos (lista de arquivos, scripts de configuração, etc.) e remove os backups dos arquivos substituídos. Este é o ponto sem volta: o dpkg
não tem mais acesso a todos os elementos necessários para retornar ao estado anterior.
Finalmente, o dpkg
configura o pacote executando new-postinst configure last-version-configured
.
5.2.2.2. Remoção de pacote
Aqui temos o que acontece durante uma remoção de pacote:
o dpkg
chama prerm remove
.
O dpkg
remove todos os arquivos do pacote, exceto os arquivos de configuração e os scripts de configuração.
O dpkg
executa postrm remove
. Todos os scripts de configuração, exceto postrm
, são removidos. Se o usuário não usou a opção “purge", os processos param aqui.
Para um purge completo do pacote (comando lançado com dpkg --purge
ou dpkg -P
), os arquivos de configuração são também apagados, assim como uma certa quantidade de cópias (*.dpkg-tmp
, *.dpkg-old
, *.dpkg-new
) e arquivos temporários; então o dpkg
executa um postrm purge
.
Os quatro scripts detalhados acima são complementados por um script config
, fornecido por pacotes usando debconf
para adquirir informações do usuário para a configuração. Durante a instalação, este script define em detalhes as perguntas feitas pelo debconf
. As respostas são gravadas no banco de dados do debconf
para futura referência. O script é geralmente executado pelo apt
antes de instalar pacotes, um a um para agrupar todas as perguntas e fazê-las todas ao usuário no começo do processo. Os scripts de pre- e pos-instalação podem então usar esta informação para operar de acordo com o que o usuário espera.
5.2.3. Checksums, Lista de arquivos de configuração
além dos scripts de mantenedor e dados de controle mencionados nas seções anteriores, o arquivo
control.tar.gz
de um pacote Debian pode conter outros arquivos interessantes. O primeiro,
md5sums
, contém as verificações (checksums) MD5 de todos os arquivos do pacote. Sua principal vantagem é que permite que o
dpkg --verify
(que vamos estudar em
Seção 14.3.3.1, “Auditando Pacotes com o dpkg --verify
”) verifique se estes arquivos foram modificados desde a instalação deles. Repare que quando este arquivo não existe, o
dpkg
vai gerar ele dinamicamente em tempo de instalação (e armazenar ele num banco de dados do dpkg assim como os outros arquivos de controle).
conffiles
lista arquivos do pacote que devem ser manipulados como arquivos de configuração. Arquivos de configuração podem ser modificados pelo administrador, e o dpkg
tentará preservar estas mudanças durante uma atualização de pacote.
Com efeito, nesta situação, o dpkg
se comporta o mais inteligente possível: se o arquivo de configuração padrão não mudou entre duas versões, ele não faz nada. Se, entretanto, o arquivo mudou, ele vai tentar atualizar o arquivo. Dos casos são possíveis: ou o administrador não tocou neste arquivo de configuração, e neste caso o dpkg
automaticamente instala a nova versão; ou o arquivo foi modificado, e neste caso o dpkg
pergunta ao administrador qual versão ele quer usar (a antiga com modificações ou a nova que o pacote fornece). Para auxiliar nesta decisão, o dpkg
se oferece para mostrar um “diff
” que mostra a diferença entre as duas versões. Se o usuário escolhe manter a versão antiga, a nova vai ser armazenada na mesma localização em um arquivo com o sufixo .dpkg-dist
. Se o usuário escolhe a nova versão, a antiga é mentida num arquivo com o sufixo .dpkg-old
. Outra ação disponível consiste em interromper momentaneamente o dpkg
para editar o arquivo e tentar reinstalar as modificações relevantes (previamente identificadas com o diff
).