#!/bin/bash
# Script desenvolvido por : hamacker <sirhamacker[em]gmail.com>
# Data : 14/Ago/2009
# Objetivo : Turbinar o backup e acabar com a necessidade de compactar
# pastas inteiras, compactando apenas os arquivos que há
# na pasta e mantendo a estrutura original de pastas da
# unidade de origem.
# Uso : Faz backup de arquivos/pastas selecionadas para discos usb
# O importante neste script é a funcao do_copy que faz
# a cópia de pastas selecionadas para a unidade de destino
# compactando-os com gzip apenas quando a extensão do arquivo
# já não for um arquivo compactado, por exemplo, não faz sentido
# compactar um arquivo jpeg, avi ou mp3, pois todos eles já são
# arquivos compactados. O script tambem possui linhas de restrição,
# isto é, a variavel LISTA_NAO_SALVAR contem extensoes de arquivos
# temporarios que não devem ser copiados.
# Além disso, o arquivo mantém a mesma estrutura do que era na origem, ex:
# Original :
# /home/fulano/planilhas/compras.xls
# /home/fulano/textos/poesias/minha-esposa.doc
# /home/fulano/musicas/mp3/testando-minha-voz.mp3
# Ficará assim na unidade de destino do backup (supondo que fosse em /media/usbdisk) :
# /media/usbdisk/home/fulano/planilhas/compras.xls.gz
# /media/usbdisk/home/fulano/textos/poesias/minha-esposa.doc.gz
# /media/usbdisk/home/fulano/musicas/mp3/testando-minha-voz.mp3
# Agora voce deve ter entendido o objetivo do script, fazer o backup de forma mais veloz
# e sem a necessidade de arquivos de logs que digam o que há dentro de cada .zip ou .tar.gz
# como seria necessario se fosse compactar as pastas inteiras
# Modo de restaurar o backup :
# Os arquivos sao compactados com o gzip, assim basta usar um gunzip para descompacta-lo.
# Se voce quiser transformar os arquivos compactados em arquivos descompactaados
# de uma pasta/subpasta recursivamente, é só executar:
# gunzip -r /local/da/pasta/onde/esta/o/backup
# e todos os arquivos que estiverem sido compactados com o gzip serao transformados em descompactados.
# Voce deve certificar-se antes de que o local onde estarao sendo transformados/descompactados tenha
# espaço suficiente.
#
############
# funcoes #
############
function log() {
if [ -z "$1" ] ; then
echo "Parametro para log esta vazio"
return
fi
if [ -z "$backup_title" ] || [ "$backup_title" = "" ] ; then
backup_title="backup-`date +%Y-%m-%d`"
fi
if [ -z "$backup_file_log" ] || [ "$backup_file_log" = "" ] ; then
backup_file_log="/var/log/$backup_title.log"
fi
if ! [ -f "$backup_file_log" ] ; then
echo "Arquivo para registrar log [$backup_file_log] não existe !"
echo -ne "Criando um arquivo vazio..."
touch "$backup_file_log"
fi
echo "$1"
echo "$1" >>$backup_file_log
}
function do_remover_acentuacao {
RETURN_STRING=""
ORIGINAL_STRING="$1"
NEW_STRING=""
SUBST_CHAR="_"
ACCEPT_CHARS="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!-_=+(){}[]\\,./"
if [ -f "/usr/bin/unaccent" ] ; then
NEW_STRING=`/usr/bin/unaccent UTF-8 "$ORIGINAL_STRING"`
if [ -z "$NEW_STRING" ] || [ "$NEW_STRING" = "" ] ; then
NEW_STRING="$ORIGINAL_STRING"
fi
fi
LEN=${#NEW_STRING}
POS=0
while [ $POS -le $LEN ] ; do
CHAR="${NEW_STRING:$POS:1}"
if [[ "$ACCEPT_CHARS" =~ "$CHAR" ]] ; then
RETURN_STRING="$RETURN_STRING$CHAR"
else
RETURN_STRING="$RETURN_STRING$SUBST_CHAR"
fi
POS=$((POS+1))
done
NEW_LEN=${#RETURN_STRING}
if [ $LEN != $NEW_LEN ] ; then
RETURN_STRING="$ORIGINAL_STRING"
fi
}
function do_copy() {
# copia uma pasta de um local de origem
# para um local de destino
# Porem faz a compactacao para o destino
copiar_de_origem="$1"
copiar_para_destino="$2"
RESULT_VALUE="OK"
LISTA_NAO_COMPACTAR=".7z .ace .ain .alz .apz .ar .arc .ari .arj .ark .axx .b64 .ba .bh .boo .bz .bz2 .bzip \
.bzip2 .c00 .c01 .c02 .car .cbr .cbz .cp9 .cpgz .cpt .dar .dd .deb .dgc .dist .ecs .efw \
.fdp .gca .gz .gzi .gzip .ha .hbc .hbc2 .hbe .hki .hki1 .hki2 .hki3 .hpk .hyp .ice .ipg \
.ipk .ish .j .jgz .jic .kgb .lbr .lemon .lha .lnx .lqr .lzh .lzm .lzma .lzo .lzx .md .mint \
.mpkg .mzp .p7m .package .pae .pak .paq6 .paq7 .paq8 .par .par2 .pbi .pcv .pea .pf .pim .pit \
.piz .pkg .pup .pup .puz .pwa .qda .r00 .r01 .r02 .r03 .rar .rev .rk .rnc .rpm .rte .rz .rzs \
.s00 .s01 .s02 .s7z .sar .sdc .sdn .sea .sen .sfs .sfx .sh .shar .shk .shr .sit .sitx .spt \
.sqx .sqz .tar .taz .tbz .tbz2 .tg .tgz .tlz .tz .uc2 .uha .vsi .wad .war .wot .xef .xez \
.xpi .xx .y .yz .z .z01 .z02 .z03 .z04 .zap .zip .zipx .zix .zoo .zz .jpg .png .gif .cab .exe .avi .mpg .mp3 .mp2 .aac"
LISTA_NAO_SALVAR=".\$\$\$ .tmp .swp .lnk"
if [ "$copiar_de_origem" = "" ] ; then
log "Erro na copia de arquivos : O endereco de origem não foi informado."
return
fi
if [ "$copiar_para_destino" = "" ] ; then
log "Erro na copia de arquivos : O endereco de destino não foi informado."
return
fi
if ! [ -d "$copiar_para_destino" ] ; then
mkdir -p "$copiar_para_destino"
fi
# lendo todos os arquivos na pasta de origem e jogando para dentro de um arquivo temporario
temp=`mktemp`
find "$copiar_de_origem/" -type f >$temp
while read ARQ_ATUAL ; do
ARQ_ATUAL_PASTA=`dirname "$ARQ_ATUAL"`
NOME_ARQUIVO=`basename "$ARQ_ATUAL"`
# entao remover a acentuacao que houver no nome de arquivo
do_remover_acentuacao "$NOME_ARQUIVO"
NOME_ARQUIVO="$RETURN_STRING"
# Apenas nomes/extensoes de arquivos compactados em minusculo
NOME_ARQUIVO=`echo "$NOME_ARQUIVO" | tr [:upper:] [:lower:]`
NOME_ARQUIVO_EXT=${NOME_ARQUIVO#*.}
NOME_ARQUIVO_EXT=`echo "$NOME_ARQUIVO_EXT" | tr [:upper:] [:lower:]`
# remover a acentuacao que houver no nome da pasta
do_remover_acentuacao "$copiar_para_destino/$ARQ_ATUAL_PASTA"
NOVA_PASTA="$RETURN_STRING"
# trocando //mnt por /
NOVA_PASTA=${NOVA_PASTA//\/\/mnt/\/}
# trocando //media/ por /
NOVA_PASTA=${NOVA_PASTA//\/\/media/\/}
# As linhas a seguir vao determinar se havera compactacao ou se realmente
# é necessario fazer o backup de tal arquivo
COMPACTAR_ARQUIVO="S"
SALVAR_ARQUIVO="S"
# tratando arquivos que não devem ser salvos no backup
[[ "$LISTA_NAO_SALVAR" =~ "$NOME_ARQUIVO_EXT" ]] && SALVAR_ARQUIVO="N"
[[ "$ARQ_ATUAL" =~ "RECYCLER" ]] && SALVAR_ARQUIVO="N"
[ "$NOME_ARQUIVO" = "thumbs.db" ] && SALVAR_ARQUIVO="N"
# tratando de nomes de arquivos que não devem ser compactados
[ "$NOME_ARQUIVO" = "setup.exe" ] && COMPACTAR_ARQUIVO="N"
[ "$NOME_ARQUIVO" = "install.exe" ] && COMPACTAR_ARQUIVO="N"
[ "$NOME_ARQUIVO" = "instalar.exe" ] && COMPACTAR_ARQUIVO="N"
if [ "$SALVAR_ARQUIVO" = "S" ] ; then
! [ -d "$NOVA_PASTA" ] && mkdir -p "$NOVA_PASTA"
[[ "$LISTA_NAO_COMPACTAR" =~ "$NOME_ARQUIVO_EXT" ]] && COMPACTAR_ARQUIVO="N"
if [ "$COMPACTAR_ARQUIVO" = "S" ] ; then
echo "[$NOME_ARQUIVO_EXT] transferindo [$ARQ_ATUAL] para [$NOVA_PASTA/$NOME_ARQUIVO.gz]"
gzip -c "$ARQ_ATUAL" >"$NOVA_PASTA/$NOME_ARQUIVO.gz"
if [ $? -ne 0 ] ; then
log "[backup-falhou] : erro ao copiar [$ARQ_ATUAL] para [$NOVA_PASTA/$NOME_ARQUIVO.gz]"
RESULT_VALUE="FALHOU"
fi
else
echo "[$NOME_ARQUIVO_EXT] transferindo [$ARQ_ATUAL] para [$NOVA_PASTA/$NOME_ARQUIVO]"
cp "$ARQ_ATUAL" "$NOVA_PASTA/$NOME_ARQUIVO"
if [ $? -ne 0 ] ; then
log "[backup-falhou] : erro ao copiar [$ARQ_ATUAL] para [$NOVA_PASTA/$NOME_ARQUIVO]"
RESULT_VALUE="FALHOU"
fi
fi
fi
done < $temp
[ -f "$temp" ] && rm -f "$temp"
}
function do_copy_7z() {
# copia uma pasta de um local de origem
# para um local de destino
# Porem faz a compactacao para o destino
copiar_de_origem="$1"
copiar_para_destino="$2"
if [ -z "$backup_title" ] || [ "$backup_title" = "" ] ; then
backup_title="backup-`date +%Y-%m-%d`"
fi
if [ -z "$backup_file_log" ] || [ "$backup_file_log" = "" ] ; then
backup_file_log="/var/log/$backup_title.log"
fi
RESULT_VALUE="FALHOU"
#### USANDO 7ZIP ####
COMPACTAR="/usr/bin/7z a -y -t7z -l -m0=lzma -mx=3 -mfb=64 -md=32m -ms=on -v100m "
COMPACTAR_EXT="7z"
COMPACTAR_CATALOGAR="/usr/bin/7z l "
if [ "$copiar_de_origem" = "" ] ; then
log "Erro na copia de arquivos : O endehttp://pastebin.com/f73e5457creco de origem não foi informado."
return
fi
if [ "$copiar_para_destino" = "" ] ; then
log "Erro na copia de arquivos : O endereco de destino não foi informado."
return
fi
if ! [ -d "$copiar_para_destino" ] ; then
mkdir -p "$copiar_para_destino"
fi
unset backup_lista_subpasta
TEMP_FILE=`mktemp`
find $copiar_de_origem/* -maxdepth 0 -type d >$TEMP_FILE
while read PASTA_ATUAL ; do
backup_lista_subpasta=( "${backup_lista_subpasta[@]}" "$PASTA_ATUAL" )
done < $TEMP_FILE
for copiar_de_origem in "${backup_lista_subpasta[@]}" ; do
# se tiver instalado o programa /usr/bin/unaccent entao removo o acento
# no nome do arquivo compactado
if [ -f "/usr/bin/unaccent" ] ; then
backup_file=`/usr/bin/unaccent UTF-8 "$copiar_de_origem"`
else
backup_file="$copiar_de_origem"
fi
# Apenas nomes compactados em minusculo
backup_file=`echo "$backup_file" | tr [:upper:] [:lower:]`
# trocando // por servidor_ (caso de a origem for um endereco smb //server/compartilhamento)
if [ "${backup_file:0:2}" = "//" ] ; then
backup_file=${copiar_de_origem//\/\//servidor_}
else
# removendo o primeiro "/" do endereco para compor o nome nome
if [ "${backup_file:0:1}" = "/" ] ; then
backup_file=${backup_file:1}
fi
fi
# trocando / por :
backup_file=${backup_file//\//:}
# trocando :mnt: por nada
backup_file=${backup_file//:mnt:/}
# trocando :media: por nada
backup_file=${backup_file//:media:/}
# trocando : por _
backup_file=${backup_file//:/_}
# acrescentando o caminho completo
backup_file="$copiar_para_destino/$backup_title-$backup_file.$COMPACTAR_EXT"
# instrucao para realizacao do backup, o algarismo "2" no final da linha
# ira redirecionar mensagens de erro (stderr) para o arquivo de log, atenção que
# nem todos os compactadores enviam mensagens de erro para strerr, é o caso
# do programa zip
$COMPACTAR "$backup_file" "$copiar_de_origem" 2>>$backup_file_log
# verificando se ouve erro
if [ $? -ne 0 ] ; then
RESULT_VALUE="FALHOU"
log "Backup de [$copiar_de_origem] completado porém com alguns erros, verifique o log para saber quais são."
else
log "Backup de [$copiar_de_origem] completado com sucesso."
RESULT_VALUE="OK"
fi
if [ -f "$backup_file" ] || [ -f "$backup_file.001" ] ; then
# Catalogando o arquivo de backup recem-criado
[ -f "$backup_file" ] && $COMPACTAR_CATALOGAR "$backup_file" >"$backup_file.txt"
[ -f "$backup_file.001" ] && $COMPACTAR_CATALOGAR "$backup_file.001" >"$backup_file.txt"
fi
done
}
############################
# Inicio do Programa #
############################
backup_title="backup-`date +%Y-%m-%d`"
backup_file_log="/var/log/$backup_title.log"
if ! [ -d "`dirname $backup_file_log`" ] ; then
mkdir -p "`dirname $backup_file_log`"
fi
# local de destino do backup
# se for uma unidade usb, nao esqueça de monta-la primeiro
destino="/media/disk"
# lista de pastas a serem backupeadas
# basta duplicar uma linha para acrescentar novas pastas
# para serem backupeadas
unset backup_lista
backup_lista=( "${backup_lista[@]}" "/home/fulano" )
backup_lista=( "${backup_lista[@]}" "/home/fulano/.ecryptfs" )
backup_lista=( "${backup_lista[@]}" "/home/fulano/.mozilla" )
backup_lista=( "${backup_lista[@]}" "/home/dados" )
backup_lista=( "${backup_lista[@]}" "/var/cache/apt/archives" )
# realizando o backup dos volumes alistados acima
# use do_copy para fazer o backup com compactacao individual de arquivos,
# ou use do_copy_7z para fazer o backup com compactacao por pastas
for origem in "${backup_lista[@]}" ; do
do_copy_7z "$origem" "$destino"
if [ "$RESULT_VALUE" != "OK" ] ; then
echo "Backup feito, porém com falhas !"
else
echo "Backup feito com sucesso !"
fi
done
log "Se precisar consultar mensagens de erro, veja [$backup_file_log]."
exit 0;