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.