No lugar extrai o arquivo tar

12

Eu tenho um pequeno dilema aqui ...

Eu precisava mover cerca de 70 GB de arquivos de um servidor para outro, então decidi que colocá-los no arquivo seria o caminho mais rápido.

No entanto, o servidor de recebimento só tem 5 GB de espaço depois de receber o arquivo tar.

Existe alguma maneira de extrair o tar 'in-place'? Eu não preciso manter o arquivo depois de ter sido extraído, então eu queria saber se é possível fazer isso.

Editar: deve-se notar que o arquivo já foi enviado e gostaria de evitar o reenvio através de um método diferente.

    
por anonymous coward 25.06.2010 / 15:14

4 respostas

11

% tar czf - stuff_to_backup | ssh backupmachine tar xvzf -

isso se traduz em:

  • tar e comprime 'stuff_to_backup' para stdout
  • faça login no 'backupmachine' por meio do ssh
  • execute 'tar' no 'backupmachine' e descompacte o material vindo de stdin

Eu pessoalmente usaria 'rsync over ssh' para transferir as coisas, porque você pode continuar transferindo coisas se a conexão quebrar:

% rsync -ar --progress -e 'ssh' 'stuff_to_backup' user@backupmachine:/backup/

que transferirá tudo, de 'stuff_to_backup' para a pasta 'backup' no 'backupmachine'. se a conexão quebrar, repita o comando. Se alguns arquivos em 'stuff_to_backup' mudarem, repita o material, apenas a diferença será transferida.

    
por 25.06.2010 / 15:22
6

Se a outra máquina tiver o ssh, recomendo o rsync como outra alternativa que não use um arquivo tar:

rsync -avPz /some/dir/ user@machine:/some/other/dir/

E tenha cuidado com os principais /

Editar atualização

Bem, eu vejo como agora isso é uma grande melhora se você não conseguir excluí-la e recomeçar com o rsync. Eu provavelmente tentaria um extrato seletivo e excluiria do tar.

extrato seletivo:

$ tar xvf googlecl-0.9.7.tar googlecl-0.9.7/README.txt
googlecl-0.9.7/README.txt

exclusão seletiva:

$ tar --delete --file=googlecl-0.9.7.tar googlecl-0.9.7/README.txt

No entanto, parece que você gastará muito tempo codificando um script para isso ...

    
por 25.06.2010 / 15:34
5

Basicamente, o que você precisa é a possibilidade de enviar o arquivo para o tar, e "lop" a frente como você vai.

No StackOverflow, alguém perguntou como truncar um arquivo na frente , mas parece que não é possível. Você ainda pode preencher o zerar do arquivo de uma maneira especial, para que o arquivo se torne um arquivo esparso , mas eu não não sei como fazer isso. Podemos truncar o final do arquivo, no entanto. Mas o tar precisa ler o arquivo para frente, não para trás.

Solução 1

Um nível de indireção resolve todos os problemas. Primeiro inverta o arquivo in-loco, então leia-o de trás para frente (o que resultará na leitura do arquivo original) e trunque o final do arquivo invertido conforme você for.

Você precisará escrever um programa (c, python, qualquer que seja) para trocar o início e o fim do arquivo, dividir por pedaço e, em seguida, canalizar esses fragmentos para tar enquanto trunca o arquivo por vez. Esta é a base para a solução 2, que talvez seja mais simples de implementar.

Solução 2

Outro método é dividir o arquivo em pequenos pedaços no local e, em seguida, excluir esses fragmentos à medida que os extrairmos. O código abaixo tem um tamanho de bloco de um megabyte, ajuste dependendo das suas necessidades. Maior é mais rápido, mas ocupa mais espaço intermediário ao dividir e durante a extração.

Divida o arquivo archive.tar:

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

Canalize esses arquivos em tar (note que precisamos da variável chunkprefix no segundo terminal):

mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.

Como usamos um pipe nomeado ( mkfifo fifo ), você não precisa canalizar todos os blocos de uma só vez. Isso pode ser útil se você estiver realmente com pouco espaço. Você pode seguir os seguintes passos:

  • Mova, diga os últimos 10 GB para outro disco,
  • Inicie a extração com os pedaços que você ainda tem,
  • Quando o ciclo while [ -e … ]; do cat "$chunk…; done terminar (segundo terminal):
  • NÃO pare o comando tar , NÃO remova o fifo (primeiro terminal), mas você pode executar sync , apenas no caso,
  • Mova alguns arquivos extraídos que você sabe que estão completos (o tar não está parado para que os dados terminem de extrair esses arquivos) para outro disco,
  • Mova os pedaços restantes de volta,
  • Retomar a extração executando novamente as linhas while [ -e … ]; do cat "$chunk…; done .

Claro que isso é tudo haute voltige , você vai querer verificar se tudo está ok em um arquivo morto primeiro, porque se você cometer um erro, então adeus dados .

Você nunca saberá se o primeiro terminal ( tar ) realmente terminou de processar o conteúdo do fifo, portanto, se preferir, você poderá executá-lo, mas não terá a possibilidade de trocar trechos com outro disco:

chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done | tar -xf -

Aviso de isenção

Observe que, para que tudo isso funcione, seu shell, tail e truncate devem manipular inteiros de 64 bits corretamente (você não precisa de um computador de 64 bits nem de um sistema operacional para isso). O meu, mas se você executar o script acima em um sistema sem esses requisitos, você perderá todos os dados em archive.tar .

E, em qualquer caso, algo diferente do que está errado, você perderá todos os dados no arquivo archive.tar, então tenha certeza de ter um backup dos seus dados.

    
por 07.05.2012 / 23:56
0

Se você tiver arquivos objeto a serem movidos, tente removê-los. Isso economizará uma quantidade considerável de espaço.

$ strip 'find . -name "*.bin"'
    
por 01.10.2014 / 17:50