Compactados auto-extratores com bash script e tar

Artigo retirado do site Dicas-L da Unicamp

Colabora??o: Marcelo Criscuolo

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. 😉