Empacotando software com RPM, Parte 3: Acomodando as dependências de software

Neste terceiro artigo em uma série de três partes sobre o RPM Package Manager, descubra os prós e contras das dependências de software, e aprenda a controlar e personalizar seu pacote de software. (Esta série substitui uma série anterior sobre RPM escrita por Dan Poirier.)

Compartilhe seu conhecimento:  Quais são os seus truques favoritos de RPM? Inclua seus comentários abaixo.

Martin Streicher, Editor in Chief, Linux Magazine

Martin Streicher é um desenvolvedor freelancer Ruby on Rails e antigo Editor-Chefe da Linux Magazine. Martin possui um grau de Mestre em Ciência da Computação pela Universidade de Purdue e tem programa para sistemas UNIX desde 1986. Ele coleciona artes e brinquedos.


nível de autor Contribuidor do
        developerWorks

04/Mar/2010 (Primeira publicação 04/Mar/2010)

Nos primórdios da informática, cada software era monolítico. Excluindo-se a ROM usada para inicializar uma máquina e o próprio sistema operacional, cada aplicativo fornecia todas as bibliotecas e todo o código necessário para operar. Esta abordagem era apropriada, amplamente porque os computadores da época não conseguiam fazer multitarefa. Mais tarde, entretanto,os computadores avançaram de vento em popa para dar suporte a múltiplos usuários simultâneos (compartilhamento de tempo) e múltiplos aplicativos simultâneos. Com muitos usuários rodando o mesmo aplicativo e compartilhando recursos do sistema tais como o sistema de arquivo e RAM, compartilhar código tornou-se uma necessidade e uma otimização.

Hoje, quase todo sistema operacional separa o código de biblioteca do código de aplicativo e une os dois no tempo de execução. Porém uma biblioteca compartilhada—o nome para código compartilhado—tem prós e contras. Na coluna mais, cada aplicativo é menor, porque cada um não precisa ser monolítico. Além disso, um reparo de bug ou melhoria de desempenho em uma biblioteca compartilhada normalmente usada beneficia todos os aplicativos. Entretanto, a separação de aplicativo e código de biblioteca é de certo modo uma algema: A biblioteca compartilhada deve ser disponível e compatível, ou o aplicativo não poderá rodar.

A ligação entre um aplicativo e uma biblioteca é um tipo de dependência. Se você distribuir código-fonte e exigir um conjunto específico de arquivos de cabeçalho para compilar o código, isto também é uma dependência. Seu código também pode exigir uma ferramenta específica, tal como Bison ou Yacc, para compilar. Se distribuir seu software em um RPM, você deve verificar se o sistema de destino fornece todas as dependências antes de instalar seu código. Afinal, se um sistema não é adequado, há pouco motivo para instalar aplicativo.

A Parte 1 desta série demonstrou como distribuir seu software via RPM. A Parte 2 descreveu o processo de instalação e desinstalação em detalhes e explicou como instalar componentes quando um pacote complementar é instalado em algum momento posterior. Este artigo, o último da série, explora outro tópico importante —dependências de software— e discute capacidades adicionais para controlar e personalizar seu pacote de software.

Definindo dependências

Quando você criar um pacote de RPM, você pode declarar quatro tipos de dependências:

  • Se seu pacote exigir uma capacidade fornecida por outra, defina um requisito.
  • Se outros pacotes dependerem ou puderem eventualmente depender de uma capacidade em seu software, declare a capacidade que seu pacote fornece.
  • Se seu software (ou parte de seu software) não pode coexistir simultaneamente com outro pacote, especifique um conflito.
  • Se seu pacote deprecia outro pacote ou uma versão mais antiga de seu software, defina o que ficou obsoleto. Se seu pacote mudar de nome, você deve listar o nome antigo como obsoleto.

Cada dependência é listada separadamente no arquivo de especificações de RPM. A sintaxe é Type: Capability, onde Type é uma das quatro tags um tanto epônimas (Requires, Provides, Conflicts, ou Obsoletes) e Capability é o nome de um número de versão opcional. Se tiver mais de uma Capability para listar, enumere todas na mesma linha, delimitadas por um espaço ou vírgula.

Por exemplo, se seu aplicativo exigisse o Perl para executar, você especificaria isso da seguinte forma:

Requires: perl

Se seu aplicativo exigisse Perl e MySQL, você poderia escrever:

Requires: perl, mysql

Muitas vezes, um aplicativo depende de uma versão específica ou um release importante específico de um pacote. Por exemplo, se você escrever código Ruby compatível com a versão 1.9, você dependerá dessa versão do interpretador. Para expressar uma versão de dependência, adicione o número de versão a Capability:

Requires: ruby >= 1.9

É possível especificar números de versão para qualquer dos quatro tipos de dependências. A sintaxe é idêntica. Por exemplo, se o aplicativo fosse incompatível com as versões do Bash shell mais recentes que a versão 2.0, você escreveria:

Conflicts: bash > 2.0

Há seis comparadores para o número de versão:

  • package < revision exige que o package nomeado tenha um número de versão inferior à revision.
  • package > revision especifica um package mais recente que a revision.
  • package >= revision solicita um package maior ou igual à revision.
  • package <= revision exige um package menor ou igual à revision.
  • package = revision obriga uma revision específica.
  • package solicita qualquer revisão do package nomeado.

Em geral, as informações para Requires e Provides é gerada automaticamente com base na análise, pelo RPM, de seu código e seu arquivo de especificações, respectivamente. (Você pode estimar aproximadamente o que o RPM calcula para Requires usando o utilitário ldd.) Entretanto, é possível alterar estas duas listas, se necessário. Conflicts e Obsoletes são normalmente fornecidos pelo desenvolvedor de software.


Assinando seu RPM

Muitos desenvolvedores escolhem o RPM porque é fácil de usar e tem amplo suporte. Entretanto, a simplicidade também facilita para que alguém mal intencionado instale o RPM, modifique seu conteúdo e reempacote e redistribua o software como autêntico. Os sites mirror e torrents só impulsionam essa "ilegalidade." Para proteger a si próprio e àqueles que usam seu software, assine seu RPM com uma assinatura única para garantir sua autenticidade. A assinatura impede a modificação: Qualquer mudança no arquivo altera a assinatura, revelando uma falsificação.

Há três formas de assinar seu pacote. Você pode assinar o pacote quando for construído. Você pode re-assinar um pacote que já foi assinado. E você pode assinar um RPM existente que não tenha assinatura. As últimas duas opções se somam à técnica da anterior, portanto nos concentremos na assinatura de um RPM quando ele é construído.

Para começar, é necessário ter um par de chave privada-chave pública de GPG. Se não tiver uma delas, essa chave é simples de gerar. O primeiro passo é iniciar o gpg-agent, que gerencia as chaves secretas. (Os sistemas normalmente executam um único gpg-agent para todos os usuários. Verifique com seu administrador de sistema para determinar se este passo é necessário. Se os sistemas já operam o agente, pergunte como conectá-lo.)

$ gpg-agent --daemon --enable-ssh-support \
  --write-env-file "${HOME}/.gpg-agent-info"

O gpg-agent cria o arquivo .gpg-agent-info em seu diretório inicial. O arquivo contém configurações do ambiente shell necessárias para conectar-se ao agente em operação. Carregue as informações com o seguinte comando. (Digite todo o comando no prompt ou, para conveniência, adicione-o a seu arquivo de inicialização de shell.)

$ if [ -f "${HOME}/.gpg-agent-info" ]; then
  . "${HOME}/.gpg-agent-info"
  export GPG_AGENT_INFO
  export SSH_AUTH_SOCK
  export SSH_AGENT_PID
fi

Finalmente, defina uma variável adicional para apontar ao dispositivo de terminal que está atualmente em uso. (Novamente, você pode adicionar estas duas linhas a um arquivo de inicialização de shell para ficar à disposição para cada sessão interativa.)

$ GPG_TTY=$(tty)
$ export GPG_TTY

Agora você está pronto para gerar uma chave. Execute o comando gpg --gen-key, e responda aos prompts. Um exemplo de sessão de geração de chave é mostrado na Listagem 1. A entrada de dados é mostrada em negrito.

Listagem 1. Exemplo de sessão de geração de chave
$ gpg --gen-key
gpg (GnuPG) 1.4.9; Copyright (C) 2008 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)
Your selection? 1
DSA keypair will have 1024 bits.
ELG-E keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 1024
Requested keysize is 1024 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)  0
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Martin Streicher
Email address: martin.streicher@example.com
Comment: Example key for RPM
You selected this USER-ID:
    "Martin Streicher (Example key for RPM) <martin.streicher@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

Enter passphrase: ******
Retype passphrase: ******

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
-------------------.-----.---------------------.----->.-----.-----..>-----.-----

O primeiro prompt escolhe o tipo de chave (o padrão é a opção preferida). O próximo prompt define o tamanho das chaves em bits. Aqui, quando mais bits melhor, embora as chaves mais longas levem mais tempo para gerar. Se preferir, você pode configurar um vencimento na chave no próximo prompt. As três consultas seguintes pedem informações para identificar esta chave. É normal fornecer seu nome e endereço de e-mail para permitir que os usuários o contatem para obter a chave pública. Finalmente, é solicitada uma frase-código duas vezes para acrescentar uma camada adicional de segurança. Ninguém pode assinar um RPM com sua chave sem a frase-código adequada. Dependendo do nível de ocupação de seu sistema, a geração de chave pode levar segundos ou minutos.

Ao concluir, o gerador de chave cria um novo diretório chamado $HOME/.gnupg e o preenche com arquivos que representam suas chaves pública e privada. Para ver as chaves que você tem disponíveis, execute gpg --list-key. Tome nota do valor de uid: Ele contém o nome da chave que você deve usar para assinar seu RPM.

$ gpg --list-key
/home/strike/.gnupg/pubring.gpg
-------------------------------
pub   1024D/1811A3E4 2009-11-23
uid                  Martin Streicher (Example key for RPM) <martin.streicher@example.com>
sub   1024g/15BBCF06 2009-11-23

To continue, you must now set options for RPM to sign the package. Create or open the file $HOME/.rpmmacros, and add three lines:

%_signature gpg
%_gpg_path /home/strike/.gnupg
%_gpg_name Martin Streicher (Example key for RPM) <martin.streicher@example.com>

A linha %_signature seleciona o tipo de assinatura. Aqui, é colocada em gpg. O %_gpg_name especifica a ID da chave com a qual assinar. Durante a geração da chave, o nome foi definido em Martin Streicher (Exemplo de chave para RPM) <martin.streicher@example.com> (O valor da ID de usuário [UID] acima), para que seja repetido aqui. Finalmente, %_gpg_path define o caminho para suas chaves.

Com as chaves e a configuração no lugar, assinar um RPM exige uma opção adicional, --sign.

$ rpmbuild -v --sign -bb --clean SPECS/wget.spec
Enter pass phrase: 
Pass phrase is good.
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.46786
+ umask 022
...

O comando rpmbuild mostra o mesmo usado na Parte 1—a única adição é --sign. Quando solicitado a senha, insira a mesma frase-código que forneceu durante a geração da chave. O RPM build continua e assina o pacote resultante.

Você pode verificar sua assinatura para garantir que seu pacote esteja puro. Para verificar a assinatura de um RPM, execute rpm -K no próprio arquivo:

$ rpm -K wget-1.12-1.i386.rpm
wget-1.12-1.i386.rpm: (SHA1) DSA sha1 md5 (GPG) OK

Se o comando resultar OK, o arquivo é legítimo. Se você fizer o download do RPM de outro desenvolvedor, considere a verificação antes de instalar o pacote.


Ferramentas adicionais para o desenvolvimento de RPM

Se usar o RPM frequentemente para empacotamento, os arquivos de especificação se tornam um procedimento automático. Não obstante, uma ampla variedade de ferramentas está disponível para tornar mais fácil a criação de arquivos de especificação. Aqui está uma amostra (vide Recursos para os links para cada um):

  • rpmlint valida os arquivos de RPM. A ferramenta capta um bom número de enganos—instalar um arquivo binário em /etc e um arquivo de configuração em /usr são duas armadilhas comuns que o rpmlimit pode detectar—e você pode ampliá-la usando módulos personalizados. O rpmlimt é escrito em Python e exige um punhado de bibliotecas para desempenhar suas funções.
  • O Easy RPM Builder é uma ferramenta baseada em K Desktop Environment (KDE) para a montagem de pacotes. A ferramenta fornece diversos modelos para ajudar a dar início em seu desenvolvimento de RPM e fornece uma interface gráfica de usuário (GUI) a partes do arquivo de especificações. O Easy RPM Builder não substitui o rpmbuild, e é necessária certa familiaridade com o RPM para usá-lo efetivamente.
  • Se não usar KDE ou preferir trabalhar com o arquivo de especificações diretamente, é possível ampliar tanto o Vim quanto o Emacs para incluir um modo especial de especificações, que destaca a sintaxe do arquivo de especificações e determina a criação e manutenção de um arquivo de especificações.
  • Embora não uma ferramenta propriamente dita, a página de Diretrizes de RPM do Projeto Fedora fornece uma vasta lista das melhores práticas. Na verdade, se pretender distribuir seu software no Fedora, preste atenção especial nos requisitos para novos pacotes. Além disso, as diretrizes descrevem como empacotar os aplicativos com base em diversas plataformas populares, inclusive o Eclipse, Perl e Ruby. O empacotamento de software para um interpretador específico é especialmente envolvido, porque o software empacotado pode incluir scripts, binários e fonte que devem ser reconstruídos durante a instalação diretamente na máquina de destino. Por exemplo, um módulo Perl pode ser parte código Perl e parte C. Você também pode encontrar uma versão do guia de software RPM oficial no site do Fedora (vide Recursos abaixo para o link).

Ferramentas adicionais ajudam a instalar e gerenciar RPMs. Em geral, estas ferramentas são destinadas a administradores de sistema, mas você pode considerá-las úteis para ajudar a validar suas instalações e gerenciar o software de seu próprio sistema de desenvolvimento. Se usar seu próprio desenvolvimento de sistema para teste, você pode considerar as ferramentas úteis para purgar pacotes inativos.


Conclusão

o RPM recebe manutenção ativa. É possível rastrear os esforços na nova home page do projeto (Vide Recursos). Existem ferramentas de RPM para a maioria das distribuições Linux, inclusive Debian. A última versão do RPM é 5.2.0, que foi lançada em julho de 2009. As metas do projeto RPM permanecem as mesmas: "Facilitar a obtenção de pacotes dentro de fora do sistema. Facilitar a verificação de se um pacote foi instalado corretamente. Facilitar para o construtor de pacote. Fazer iniciar com o código-fonte original. Fazer funcionar em diferentes arquiteturas de computador."

O desenvolvimento de RPM pode ser completo, porque a instalação do software é igualmente complexa. Esta série abordou quase todos os tópicos. É possível encontrar uma grande quantidade de informações sobre o desenvolvimento de RPM na Web. Há tutoriais, fóruns e até mesmo um canal de IRC dedicado a este tópico (visite #rpm.org em Freenode). Além disso, é possível encontrar centenas, senão milhares de outros RPMs online. Se você se deparar com um problema especialmente complicado, encontre outro pacote RPM com similaridade e sonde seu arquivo de especificações para deduzir uma solução.

Se for desenvolvedor de software ou administrador de sistema, fornecer seu aplicativo como um pacote torna muito mais fáceis as instalações, atualizações e a manutenção. Novamente, se você construir e empacotar com RPM, ele chegará.

Recursos

Aprender

Obter produtos e tecnologias

  • Saiba mais e faça o download de rpmlint.
  • Saiba mais e faça o download de Easy RPM Builder.
  • Com o software de teste IBM, disponível para download diretamente no developerWorks, faça seu próximo projeto de desenvolvimento em Linux.

Discutir

  • Envolva-se na comunidade My developerWorks. Conecte-se com outros usuários do developerWorks enquanto explora os blogs, fóruns, grupos e wikis conduzidos por desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux
ArticleID=471587
ArticleTitle=Empacotando software com RPM, Parte 3: Acomodando as dependências de software
publish-date=03042010