De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Compactados auto-extratores com bash script e tar

Colaboração: Marcelo Criscuolo

Data de Publicação: 16 de Setembro de 2005

Recentemente me deparei com o problema de criar um arquivo compactado que fosse capaz de se "auto-descompactar" e realizar algumas outras "tarefinhas burocráticas". Lembrei-me então que o instalador do J2SDK da Sun para Linux é um shell script e resolvi descobrir como ele era feito. A solução é bem elegante e simples de ser implementada, trata-se de criar um arquivo composto por um shell script no início e o arquivo compactado (binário) no final.

Suponhamos que você deseja compactar todo o diretório basedados que contém scripts SQL e enviá-lo para alguém de maneira que seja necessário apenas um comando como ./atualizar-base.sh para o arquivo seja descompactado e a base seja atualizada com base nos arquivos contidos no diretório.

Para começar, o velho tar resolve a primeira parte do problema:

  tar cvzf basedados.tar.gz basedados/``

Agora precisamos do script que vai fazer o "trabalho sujo", o atualizar-base-codigo.sh:

  #!/bin/bash
  
  # extraindo o arquivo
  tail -n +XX $0 > basedados.tar.gz # linha IMPORTANTE
  
  # Descompactando o arquivo extraído
  tar xzf basedados.tar.gz
  
  # Arquivo descompactado, hora de rodar os scripts
  for i in basedados/*; do
  echo "Rodando o script $i"
  # Aqui você poderia rodar os scripts. Por exemplo,
  # se a base da dados fosse Postgres você poderia
  # fazer: psql -U usuario base -c "\i $i" , para
  # rodar todos os scripts do diretório
  done
  
  exit 0 # outra linha IMPORTANTE

É hora de fazer o nosso trabalho sujo agora:

Vamos contar as linhas do arquivo:

  wc -l atualizar-base-codigo.sh``

Preste atenção às linhas marcadas com IMPORTANTE.

Nesse caso o wc retorna 18, re-edite o arquivo e substitua o XX da primeira linha marcada como importante por 19 (18+1), salve o arquivo sem adicionar mais nenhuma linha. Vamos juntar tudo agora:

  cat atualizar-base-codigo.sh basedados.tar.gz > atualizar-base.sh``

Pronto! Concatenamos um arquivo texto e um binário!

O tail extrai as linhas finais de um arquivo, mas quando o número de linhas é precedido pelo sinal + ele extrai todo o final do arquivo, daquela linha em diante (veja man tail), é esse o papel do -n +19.

No nosso exemplo, o tail vai extrair o final do próprio shell script (a variável $0 é expandida para o nome do arquivo atual) a partir da linha 19, que corresponde ao arquivo basedados.tar.gz contenado a ele anteriormente.

Por o último, o > basedados.tar.gz é responsável por escrever a saída do tail num arquivo ao invés de escrever na tela.

O arquivo é descompactado com o tar na linha seguinte e o seu conteúdo é processado pelo for.

Finalmente, na segunda linha marcada com IMPORTANTE, tem-se o exit 0; esse comando serve para dizer ao bash que pare de interpretar o script antes de atingir os dados binários.

Um aviso importante: não edite mais o arquivo gerado pelo cat pois se o editor colocar um EOF no final o seu arquivo compactado será corrompido. É por isso que se usa o arquivo atualizar-base-codigo.sh para fazer a edição.

Outra coisa legal que dá pra fazer com isso é gerar patches auto-aplicáveis. Ao invés de concatenar o arquivo com um compactado você concatena com a saída do diff (o patch). Neste caso o exit 0 também é essencial, pela mesma razão citada anteriormente, mas agora o arquivo gerado pode ser editado, já que um EOF a mais ou a menos não faz diferença para o patch. ;-)

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Marcelo Criscuolo