Baixe arquivos em pedaços com o DCDownloader

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

[ Hits: 18.492 ]

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

ORACLE 10.2g - Fazendo Backup

Criando usuário com poderes de root

EPD (Editor de Pacotes Debian)

rc.mailMyIp - Informa seu IP externo para o Gmail

Agendador de Taferas


  

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