Baixe arquivos em pedaços com o DCDownloader

Publicado por Davidson Francis (última atualização em 11/04/2014)

[ Hits: 18.521 ]

Download DCDownloader.sh




O Divide and Conker Downloader (não, não é da Detective Comics, kkk) permite que o download de um arquivo (em link direto) possa ser dividido em n partes de modo que o usuário possa literalmente dividir o download em fragmentos.

Vejo no mínimo duas utilidades interessantes:

- Quando é necessário baixar arquivos realmente grandes e você dispõe de mais de uma conexão com a internet.
Desta forma um arquivo de 10 GB poderia ser facilmente distribuído entre 10 amigos, cada um deles baixando partes diferentes do mesmo arquivo simultaneamente; no término do download, basta fazer a junção das partes e obterá o arquivo original novamente.

- Quando o servidor limita a banda, com o uso de downloads simultâneos pode obter um aproveitamento muito maior da internet em questão. O que ilustro nesse vídeo: https://www.youtube.com/watch?v=aG59N51cWAQ

O script possui basicamente três comandos:

-g url qtd - Nesta opção geramos os arquivos de configuração que serão utilizados em cada máquina separadamente, onde:
    url é o link do download e qtd é quantidade de máquinas e/ou instâncias que serão executadas.

-r file - Realiza a leitura do arquivo de configuração, onde file é o arquivo gerado pela opção "-g". Deve-se atentar ao executar o download em pastas separadas, devido aos arquivos auxiliares gerados no processo.

-j - Realiza o "join" de todos os arquivos baixados em um único arquivo.

Um exemplo de uso seria:

$ ./DCDownloader.sh -g http://link/file.tar.gz 2

PC1:
$ ./DCDownloader.sh -r DC1.conf

PC2:
$ ./DCDownloader.sh -r DC2.conf

Posteriormente:

$ ./DCDownloader -j

É isso pessoal, espero que tenham gostado e fico a disposição a quaisquer dúvidas, críticas e sugestões.

  



Esconder código-fonte

#!/bin/bash
clear

echo "------------------------------------------------"
echo "    Divide and Conker Downloader, by Theldus"
echo "------------------------------------------------"
echo ""

gerarConfiguracao()
{
    #Verifica se quantidade e valida
    tam=`curl -sI $1 | grep Content-Length | cut -d ' ' -f 2 | sed 's/\r$//'`
    tam=`echo "scale=2;$tam/1048576" | bc`
    tam=`echo "$tam/$2" | bc`

    if [ $tam -lt 1 ]; then
        echo "> Por favor, entre com uma distribuicao >= 1MB por execucao"
    else
        #Distribuicao de blocos OK
        if [ $2 -lt 2 ]; then
            echo "> Escolha algo >=2"
        else
            if [ $2 -eq 2 ]; then
                #Processa = 2,gera config e inicio e fim

                rm DC1.conf 2>/dev/null
                rm DC2.conf 2>/dev/null
                #Inicio
                echo "start" >> DC1.conf
                echo $tam    >> DC1.conf
                echo $1          >> DC1.conf
                echo "1"         >> DC1.conf

                #Final
                echo "final" >> DC2.conf
                echo $tam        >> DC2.conf
                echo $1          >> DC2.conf
                echo "2"         >> DC2.conf

                echo "> Arquivos de configuracao gerados com sucesso"
                echo "> $[tam*$2] MB divididos em $2 partes de $tam MB cada, :D"
                echo -e "> Use o arquivo de configuracao para o download individual\n  em cada pc"

            else
                #Processa > 2
                rm DC*.conf 2>/dev/null

                #Start
                echo "start" >> DC1.conf
                echo $tam    >> DC1.conf
                echo $1          >> DC1.conf
                echo "1"         >> DC1.conf

                quantidade=$[$2-2]
                indice=2
                tam_ac=$tam

                #Middle
                while [ $quantidade -gt 0 ]
                do
                    echo "middle" >> DC$indice.conf
                    echo $tam_ac    >> DC$indice.conf
                    echo $[tam_ac+tam] >> DC$indice.conf
                    echo $tam           >> DC$indice.conf
                    echo $1             >> DC$indice.conf
                    echo $indice    >> DC$indice.conf

                    quantidade=$[quantidade-1]
                    indice=$[indice+1]
                    tam_ac=$[tam_ac+tam]
                done

                #Final
                echo "final"    >> DC$indice.conf
                echo $tam_ac    >> DC$indice.conf
                echo $1             >> DC$indice.conf
                echo $indice    >> DC$indice.conf

                echo "> Arquivos de configuracao gerados com sucesso"
                echo "> $[tam*$2] MB divididos em $2 partes de $tam MB cada, :D"
                echo -e "> Use o arquivo de configuracao para o download individual\n  em cada pc"
            fi
        fi
    fi
}

lerConfiguracao()
{
    if [ -e "$1" ]; then
        #Verifica o tipo do .conf para processamento individual
        tipo=`head -n1 $1`
        echo "Caso esteja executando em uma mesma maquina todos os arquivos de"
        echo "configuracao, atente-se em executar o script em pastas diferentes!"
        echo "OK?"
        read trash

        if [ "$tipo" == "start" ]; then
            #Processa inicio
            tam=`head -n2 DC1.conf | tail -n1`
            url=`head -n3 DC1.conf | tail -n1`
            fileName=`echo $url | tr "/" "\n" | tail -n1`

            echo "PC 1, baixando..."

            rm wget-log* 2>/dev/null
            rm $fileName 2>/dev/null
            pid=`wget -b $url | head -n1 | sed 's/[^0-9]//g'`

            while [ ! -f $fileName ]
            do
                #Sim, nao faz nada,apenas para obter o delay necessario
                #antes de verificar se arquivo existe
                echo "nop" > /dev/null
            done

            while [ $[`wc -c $fileName | cut -d' ' -f1`/1048576] -lt $tam ]
        do
                echo -e "`tail -n1 wget-log`"
                sleep 1
        done
            kill $pid

            echo "Download concluindo, limando..."
            dd if=./$fileName of=./DCDpc1 bs=1M count=$tam 2>/dev/null
            rm $fileName
            rm wget-log* 2>/dev/null

            echo "Parte 1 concluida com sucesso, ;)"

        else
            if [ "$tipo" == "middle" ]; then

                tamStub=`head -n2 $1 | tail -n1`
                tamBaix=`head -n3 $1 | tail -n1`
                tamBloco=`head -n4 $1 | tail -n1`
                url=`head -n5 $1 | tail -n1`
                fileName=`echo $url | tr "/" "\n" | tail -n1`
                position=`tail -n1 $1`

                #Gera um 'stub'
                rm $fileName 2>/dev/null
                dd if=/dev/zero of=./$fileName bs=1M count=$tamStub 2>/dev/null

                echo "PC $position, baixando..."

                rm wget-log* 2>/dev/null
                pid=`wget -b -c $url | head -n1 | sed 's/[^0-9]//g'`

                while [ ! -f "wget-log" ]
                do
                    #Sim, nao faz nada,apenas para obter o delay necessario
                    #antes de verificar se arquivo existe
                    echo "nop" > /dev/null
                done

                while [ $[`wc -c $fileName | cut -d' ' -f1`/1048576] -lt $tamBaix ]
            do
                    echo -e "`tail -n1 wget-log`"
                    sleep 1
            done
                kill $pid

                echo "Download concluindo, limando..."
                dd if=./$fileName of=./DCDtmp$position bs=1M ibs=1M skip=$tamStub 2>/dev/null
                rm $fileName 2>/dev/null

                dd if=./DCDtmp$position of=./DCDpc$position bs=1M count=$tamBloco 2>/dev/null
                rm DCDtmp$position 2>/dev/null
                rm wget-log* 2>/dev/null

                echo "Parte $position concluida com sucesso, ;)"
            else
                if [ "$tipo" == "final" ]; then

                    tam=`head -n2 $1 | tail -n1`
                    url=`head -n3 $1 | tail -n1`
                    fileName=`echo $url | tr "/" "\n" | tail -n1`
                    position=`tail -n1 $1`

                    #Gera um 'stub'
                    rm $fileName 2>/dev/null
                    dd if=/dev/zero of=./$fileName bs=1M count=$tam 2>/dev/null

                    echo "PC $position, baixando..."

                    rm wget-log* 2>/dev/null
                    pid=`wget -b -c $url | head -n1 | sed 's/[^0-9]//g'`

                    while [ ! -f "wget-log" ]
                    do
                        #Sim, nao faz nada,apenas para obter o delay necessario
                        #antes de verificar se arquivo existe
                        echo "nop" > /dev/null
                    done

                    while [ -n "`pgrep wget | grep $pid`" ]
                do
                        echo -e "`tail -n1 wget-log`"
                        sleep 1
                done

                echo "Download concluindo, limando..."
                    dd if=./$fileName of=./DCDpcFinal bs=1M ibs=1M skip=$tam 2>/dev/null
                    rm $fileName 2>/dev/null
                    rm wget-log* 2>/dev/null

                    echo "Parte $position concluida com sucesso, ;)"
                fi
            fi
        fi
    else
        error
    fi
}

Join()
{
    echo "Antes de iniciar-mos o merge, certifique-se de que todos os arquivos"
    echo "estao em um mesmo diretorio!"
    echo "OK?"
    read trash

    echo "Juntando downloads..."
    cat DCDpc* > DCDFinal
    echo "Arquivo finalizado: DCDFinal, tenha um bom dia!"
}

error()
{
    echo "-----------------------------------------------------------------------------"
    echo "Parametros incorretos:"
    echo "DCDownloader [operando] -g, -r"
    echo "-g url quantidade - (Gera os arquivos de configuracao para cada download)"
    echo "-r DCx.conf       - (Le o x-esimo arquivo de configuracao para efetuar o"
    echo "                     download)"
    echo "-j                - (Junta as partes em um unico arquivo novamente)"
    echo "-----------------------------------------------------------------------------"
}

if [ "$1" == "-g" ]; then
    gerarConfiguracao $2 $3
else
    if [ "$1" == "-r" ]; then
        lerConfiguracao $2
    else
        if [ "$1" == "-j" ]; then
            Join
        else
            error
        fi
    fi
fi

Scripts recomendados

Script para limpar os caches do proxy (squid)

Fazer backup da trilha mbr

Atualização automática do Slackware

Monitorando processo do Squid em diferentes redes

Sincronizar arquivos com rsync


  

Comentários
[1] Comentário enviado por removido em 14/04/2014 - 10:35h

Muito louco, adorei, obrigado por compartilhar.

[2] Comentário enviado por DavidsonDFGL em 26/04/2014 - 03:34h


[1] Comentário enviado por tropper em 14/04/2014 - 10:35h:

Muito louco, adorei, obrigado por compartilhar.


Fico feliz que tenha gostado, qualquer coisa, tamos aí, :D


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts