Ir para conteúdo
  • Como criar um pacote deb “na unha”

       (0 análises)

    Fernando Mercês

    Aproveitando que farei uma apresentação sobre pacotes deb na comemoração do 18º aniversário do Debian GNU/Linux, decidi escrever este artigo, para mostrar o que é um pacote deb e como ele pode ser gerado de forma quase artesanal.

    O objetivo deste artigo é mostrar o que é um pacote deb e como ele se comporta. Mostrarei como olhar o conteúdo de um pacote deb a fim de copiar sua estrutura para gerar um novo, coisa que fiz quando comecei a me interessar pelo assunto.

    Este artigo faz parte de um objetivo maior, que é atrair colaboradores para a comunidade Debian. Um pacote “caseiro” não será aceito nos repositórios oficiais, mas iniciará o leitor no mundo do empacotamento e, quem sabe, despertará o Debian Maintainer que há em você.:)

    1. Introdução

     

    Imagine um mundo sem pacotes deb. Todos os softwares livres seriam distribuídos em código-fonte. Você seria obrigado a baixar, compilar e instalar. Fácil? Nem sempre. Os programas possuem dependências de bibliotecas que o desenvolvedor usou. Na máquina dele essas bibliotecas estão instaladas, na sua provavelmente não. Então seria preciso instalá-las antes de compilar o programa que você quer.

    Claro que os jargões utilizados aqui só fazem sentido para usuários avançados. O Linux não teria conquistado a popularidade que tem hoje se os usuários leigos tivessem que compilar o Firefox para navegar na internet. Os pacotes supriram esta necessidade e hoje um software inteiro com suas dezenas de dependências pode ser instalado graficamente ou com uma curta e simples linha de comando. Cabe aqui um viva ao software livre. o/

    Este artigo não é para leigos, mas para quem gostaria de entender como o pacote deb funciona.

     

    2. Pacote “caseiro” x pacote oficial

     

    Para fazer um pacote e submetê-lo ao repositório oficial, você precisa ler, compreender e seguir rígidas regras de qualidade, que podem ser encontradas nos documentos oficiais [1]. No entanto, creio que o modo mais fácil é começar por um pacote “caseiro”, que não segue a política, para entender o funcionamento e então partir para o estudo dos documentos. Foi assim que deu certo comigo e hoje mantenho o pacote do pev [2] no repositório oficial (testing).

    A comunidade Debian oferece uma série de ferramentas para criação de pacotes, sempre com foco nos pacotes oficiais. Neste artigo evitarei usar tais ferramentas, mas vou comentar, para que o leitor já se ambiente.

     

    3. Do que é feito o pacote deb

     

    Se você der uma olhada em no diretório /var/cache/apt/archives provavelmente vai encontrar vários pacotes deb. Eles estão lá porque foram baixados por você seja via Synaptic, apt-get, aptitude ou outro gerenciador de pacotes que use o dpkg.

    Antes de usar o dpkg (a ferramenta oficial) para analisar um pacote deb, vamos ver do que um pacote deb é feito. Escolhi como exemplo o pacote do wget.

    $ ls -lh wget*
    -rw-r–r– 1 fernando fernando 717K Aug 17 00:26 wget_1.12-5_amd64.deb 

    Vamos copiar o pacote para o /tmp, para manter o cache intacto:

    $ cp wget_1.12-5_amd64.deb /tmp 

    No diretório /tmp, podemos usar o comando file para ver o tipo de arquivo do pacote deb:

    $ cd /tmp
    $ file wget_1.12-5_amd64.deb
    wget_1.12-5_amd64.deb: Debian binary package (format 2.0)

    A libmagic (usada pelo file) reconhece o pacote corretamente. Mas será que os desenvolvedores criaram realmente um tipo de arquivo completamente novo para armazenar o conteúdo de um programa? Sabemos que dentro de um pacote deb há os arquivos executáveis do programa, documentação, ícones etc. Não seria viávei utilizar um agrupador de arquivos com compressão ou coisa do tipo?

    Eric Raymond, um dos hackers mais respeitados do mundo detém a seguinte crença, escrita em seu documento “How to become a hacker” [3]: “No problem should ever have to be solved twice” (Nenhum problema deve ser resolvido duas vezes). Ou seja, não é preciso “reinventar a roda”, como dizemos popularmente. Com base nesta inteligente frase, os desenvolvedores do dpkg e do formato deb usaram sim o que já exitia para atingir seus objetivos, o que foi brilhante.

    Na página de manual do formato deb(5), podemos ler:

    “The file is an ar archive with a magic value of !<arch>.”

    Para conferir, comande:
     

    $ man deb

    Então estamos falando de um arquivo ar [4]. Conforme você pode ver na referência, ar é um utilitário do conjunto binutils, do projeto GNU, para criar, modificar e extrair arquivos. É um agrupador, assim como o tar.

    Vamos conferir o magic value como disse o man?

    $ hd -n 64 wget*
    00000000  21 3c 61 72 63 68 3e 0a  64 65 62 69 61 6e 2d 62  |!<arch>.debian-b|
    00000010  69 6e 61 72 79 20 20 20  31 33 31 31 34 35 31 34  |inary   13114514|
    00000020  35 31 20 20 30 20 20 20  20 20 30 20 20 20 20 20  |51  0     0     |
    00000030  31 30 30 36 34 34 20 20  34 20 20 20 20 20 20 20  |100644  4       |

    Certinho. O tal “!<arch>” esta no início do arquivo, o que sugere ser o seu magic number. Vamos listar o conteúdo deste arquivo com a ferramenta ar então:

    $ ar tv wget*
    rw-r–r– 0/0      4 Jul 23 17:04 2011 debian-binary
    rw-r–r– 0/0   2432 Jul 23 17:04 2011 control.tar.gz
    rw-r–r– 0/0 731281 Jul 23 17:04 2011 data.tar.gz

    Então temos um arquivo ar com três arquivos. E se criarmos um ar com um arquivo qualquer, o que será que o file retorna?

    $ echo “meu texto” > texto.txt
    
    $ ar r teste.deb texto.txt
    ar: creating teste.deb

    O comando acima criou um arquivo ar chamado teste.deb (lembre-se que o Linux despreza extensões) e adicionou o arquivo texto.txt nele.

    $ file teste.deb
    teste.deb: current ar archive

    O file retorna que é um arquivo ar, corretamente.

    Mas por que o file reconhece como pacote do wget corretamente como binário do debian? A resposta está no código-fonte do file [5], que identifica um pacote binário se depois do magic number do ar, o arquivo contiver a string “debian-binary”. De fato, o formato ar define o magic e o nome do primeiro arquivo agrupado em seguida. Então bastaria que criássemos um arquivo ar com um arquivo debian-binary qualquer para o “enganar” o file.

    $ echo 2011 > debian-binary
    
    $ ar r fake.deb debian-binary
    ar: creating fake.deb $ file fake.deb
    fake.deb: Debian binary package (format 2011) 

    Agora sim. O file não faz nenhuma verificação adicional (e nem deveria). Mas a intenção aqui não é hackear o file (até porque estamos falando de um formato livre, com extensa documentação), e sim criar um deb “na mão”. Perceba que o formato apareceu como “2011”. Claro que é um pacote inválido e se você tentar instalar o dpkg vai gerar um erro. Nem perca seu tempo.;)

    4. Extraindo um pacote deb

     

    Voltando ao que interessa, vamos extrair o conteúdo do pacote deb do wget para conferir o que há de interessante:

    $ mkdir wget
    $ cd wget
    $ ar xv ../wget*
    x – debian-binary
    x – control.tar.gz
    x – data.tar.gz $ cat debian-binary
    2.0

    Exatamente o que o file informou. Versão 2.0 do formato deb. Beleza.

    $ tar tvzf control.tar.gz
    drwxr-xr-x root/root         0 2011-07-23 17:04 ./
    -rw-r–r– root/root      3832 2011-07-23 17:04 ./md5sums
    -rw-r–r– root/root        12 2011-07-23 17:04 ./conffiles
    -rw-r–r– root/root      1327 2011-07-23 17:04 ./control

    Acima vemos alguns arquivos de controle do pacote. O interesse maior é no arquivo “control”, necessário para um pacote funcionar. O md5sums também é legal de se ter.

    $ tar tvzf data.tar.gz
    <saída suprimida=””>
    -rw-r–r– root/root       651 2009-09-21 23:52
    ./usr/share/doc/wget/ChangeLog.README
    drwxr-xr-x root/root         0 2011-07-23 17:04 ./usr/bin/
    -rwxr-xr-x root/root    353824 2011-07-23 17:04 ./usr/bin/wget

    Já o data.tar.gz contém os dados do pacote em si, incluindo binários executáveis e documentação, todos numa estrutura bem definida. Aliás, é esta estrutura que o pacote cria ao ser instalado.

    Estou mais interessado no control.tar.gz. Vamos extraí-lo:

    $ tar xvzf control.tar.gz
    ./
    ./md5sums
    ./conffiles
    ./control $ head -5 md5sums
    1b2acae8540b64a3170dc4ce0200809e  usr/bin/wget
    d62b0aafbbacf1d54031ded4d1a5f232  usr/share/doc/wget/AUTHORS
    2f58d6d92cabcf358718a564d3e132d4  usr/share/doc/wget/ChangeLog.README
    2b95a82f1c7499025d67ff86af2d7ecd  usr/share/doc/wget/MAILING-LIST
    9e83cee67a496f5eb62aecf283e14367  usr/share/doc/wget/NEWS.gz

    Certo, vemos no arquivo md5sums, o hash MD5 de cada arquivo incluso no data.tar.gz (no entanto só imprimi 5 linhas com o head). Não seria difícil gerar isso para o nosso pacote “artesenal”.

    $ cat control
    Package: wget
    Version: 1.12-5
    Architecture: amd64
    Maintainer: Noël Köthe
    Installed-Size: 2344
    Depends: libc6 (>= 2.3), libidn11 (>= 1.13), libssl1.0.0 (>= 1.0.0), dpkg (>=
    1.15.4) | install-info
    Conflicts: wget-ssl
    Section: web
    Priority: important
    Multi-Arch: foreign
    Homepage: http://www.gnu.org/software/wget/
    Description: retrieves files from the web
    Wget is a network utility to retrieve files from the web
    using HTTP(S) and FTP, the two most widely used internet
    protocols. It works non-interactively, so it will work in
    the background, after having logged off. The program supports
    recursive retrieval of web-authoring pages as well as ftp
    sites — you can use wget to make mirrors of archives and
    home pages or to travel the web like a WWW robot.
    .
    Wget works particularly well with slow or unstable connections
    by continuing to retrieve a document until the document is fully
    downloaded. Re-getting files from where it left off works on
    servers (both HTTP and FTP) that support it. Both HTTP and FTP
    retrievals can be time stamped, so wget can see if the remote
    file has changed since the last retrieval and automatically
    retrieve the new version if it has.
    .
    Wget supports proxy servers; this can lighten the network load,
    speed up retrieval, and provide access behind firewalls.

    Este é o arquivo que descreve o pacote. A referência deste arquivo é tratada na Debian Policy [6], mas os campos mais comumente usados para pacotes simples são:

    • Package  – Nome do pacote
    • Version  – Versão do programa-versão do pacote
    • Architecture– Arquitetura para qual o programa foi compilado. Pode ser i386, amd64, dentre outras. Pode ser “all” para scripts, por exemplo.
    • Maintainer  – Aqui vai o seu nome e e-mail. O criador do pacote (não do programa a ser empacotado).
    • Installed-Size – O espaço estimado, em bytes, requerido para instalar o pacote.
    • Depends  – Os pacotes dos quais seu pacote depende. Se for um programa em Python, vai depender do interpretador python, por exemplo.
    • Homepage  – O site do programa empacotado
    • Description-A descrição do pacote. Uma linha para a descrição curta e demais para descrição longa, onde todas devem começar com um espaço e as linhas em branco devem possuir um ponto (.), que não vai aparecer no final das contas.

    Agora que já explicamos a estrutura de um pacote deb básico, vamos ver como criar um.

     

    5. Criando um pacote “artesanal”

     

    Precisamos ter o que empcotar. Então vamos criar um software de teste.

    $ mkdir /tmp/nada-1.0
    $ cd /tmp/nada-1.0
    
    $ echo -e “#include <stdio.h>nnint main()n{ntputs(“nada…”);ntreturn 0;n}” > nada.c

    Os comandos acima devem criar um arquivo nada.c, no diretório /tmp/nada-1.0, com o seguinte conteúdo:

    #include <stdio.h>
    
    int main()
    {
    	puts(“nada…”);
    	return 0;
    }

    Agora precisamos compilar o programa:

    $ gcc -o nada nada.c

    O binário “nada” precisa de uma estrutura. Então vamos colocá-lo num usr/bin:

    $ mkdir -p usr/bin
    $ mv nada usr/bin/

    NOTA: Cuidado para não tentar mover o “nada” para o /usr/bin do sistema.

    Agora temos a seguinte estrutura:

    $ find .
    . ./usr
    ./usr/bin
    ./usr/bin/nada
    ./nada.c

    Precisamos do arquivo de controle. Que tal este?

    Package: nada
    Version: 1.0
    Architecture: amd64
    Maintainer: Você <seu@email.com.br>
    Homepage: http://www.tacomnada.com
    Installed-Size: 6560
    Depends: libc6 (>= 2.2.5)
    Description: program that does nothing
    Na realidade o nada conseguie imprimir a string “nada…” na tela. Claro que
    pode servir para algo, mas nao saberia dizer para que. Talvez para aprender
    a empacotar no Debian, ou para nao fazer nada.
    .
    Depois de falar tanto, nao vou dizer mais nada.

    Basta salvar como control (sem extensão mesmo).

    Para o campo Installed-Size, eu contei os bytes do binário “nada”:

    $ wc -c nada
    6560 nada

    Já no campo Depends, é interessante avaliar a saída do ldd:

    $ ldd nada
    linux-vdso.so.1 => (0x00007fffea5ff000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcebbf5d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fcebc2fe000)

    A primeira entrada é a uma biblioteca virtual para interface com o kernel. Ela sempre existirá e também pode aparecer como linux-gate.so.1.

    Em seguida temos duas bibliotecas reais. Supondo que não saibamos em qual pacote elas se encontram, podemos usar o apt-file:

    $ apt-file search libc.so.6
    libc6: /lib/x86_64-linux-gnu/libc.so.6
    libc6-i386: /lib32/libc.so.6

    O pacote de nosso interece é o libc6. Agora, a versão da biblioteca requerida vai depender das funções que o programador utilizou. Isto consultado ser pego no site do projeto ou diretamente com o desenvolvedor. Usei 2.2.5.

    Vamos buscar a última lib que o ldd detectou:

    $ apt-file search ld-linux-x86-64.so.2
    libc6: /lib/ld-linux-x86-64.so.2
    libc6: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

    Também está no pacote libc6. Beleza, então só temos esta dependência.

    Agora precisamos gerar os arquivos control.tar.gz (com o control dentro), data.tar.gz (com toda a árvode usr dentro) e debian-binary (com a string 2.0 dentro):

    $ tar cvzf data.tar.gz usr/
    usr/
    usr/bin/
    usr/bin/nada $ tar cvzf control.tar.gz control
    control
    
    $ echo 2.0 > debian-binary
    
    $ ar r nada-1.0_amd64.deb debian-binary control.tar.gz data.tar.gz
    ar: creating nada-1.0_amd64.deb
    fernando@localhost:/tmp/wget/nada-1.0$ file nada-1.0_amd64.deb
    nada-1.0_amd64.deb: Debian binary package (format 2.0)

    Perceba que o primeiro arquivo a ser adicionado no ar é o debian-binary.

    E agora vamos testar.

    $ sudo dpkg -i nada-1.0_amd64.deb
    Selecting previously deselected package nada.
    (Reading database … 146331 files and directories currently installed.)
    Unpacking nada (from nada-1.0_amd64.deb) …
    Setting up nada (1.0) … $ nada
    nada… $ sudo dpkg -P nada
    (Reading database … 146332 files and directories currently installed.)
    Removing nada …

     

    6. Conclusão

     

    O pacote funciona. Inclusive eu fiz um script (makedeb_v2.sh) para empacotar [quase que] desta forma o Evan’s Debugger [7]. Vale a pena dar uma olhada, pois tem outros arquivos e comandos que não mencionei aqui. No entanto, ressalto que a preferência deve ser para pacotes com alta qualidade.

    Provavelmente escreverei um outro artigo sobre a forma correta de se criar pacotes, com base na política do Debian e com as ferramentas providas pela comunidade. Não é fácil fazer um pacote de qualidade, mas o primeiro passo, na minha opinião, é entender com o que estamos lidando e espero que este artigo tenha atingido este objetivo.

    [1] http://www.debian.org/doc/#manuals
    [2] http://packages.debian.org/wheezy/pev
    [3] http://catb.org/~esr/faqs/hacker-howto.html#believe2
    [4] http://www.gnu.org/s/binutils/
    [5] ftp://ftp.astron.com/pub/file/
    [6] http://www.debian.org/doc/debian-policy/ch-controlfields.html
    [7] http://codef00.com/projects#debugger


    Revisão: Leandro Fróes

    Feedback do Usuário

    Participe da conversa

    Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.
    Nota: Sua postagem exigirá aprovação do moderador antes de ficar visível.

    Visitante

    • Isso não será mostrado para outros usuários.
    • Adicionar um análise...

      ×   Você colou conteúdo com formatação.   Remover formatação

        Apenas 75 emojis são permitidos.

      ×   Seu link foi automaticamente incorporado.   Mostrar como link

      ×   Seu conteúdo anterior foi restaurado.   Limpar o editor

      ×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.


  • Conteúdo Similar

×
×
  • Criar Novo...