você está aqui: Home  → Arquivo de Mensagens Programação Shell Linux: Inscrições Abertas

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. ;-)



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