Digamos que eu tenha um arquivo de 80 GB /root/bigfile
em um sistema de 100 GB e queira colocá-lo em um arquivo /root/bigarchive.tar
Obviamente, preciso excluir este arquivo ao mesmo tempo em que é adicionado ao arquivo. Daí a minha pergunta:
Como excluir um arquivo ao mesmo tempo em que é adicionado a um arquivo morto?
tar
zip
compression
gzip
user123456
fonte
fonte
Um arquivo tar não compactado de um único arquivo consiste em um cabeçalho, o arquivo e um bloco à direita. Portanto, seu principal problema é como adicionar 512 bytes de cabeçalho ao início do seu arquivo. Você pode começar criando o resultado desejado apenas com o cabeçalho:
Em seguida, copie os primeiros 10G do seu arquivo. Por uma questão de simplicidade, assumimos que seu dd pode ler / escrever 1Gib por vez:
Agora, desalocamos os dados copiados do arquivo original:
Isso substitui os dados por zeros esparsos que não ocupam espaço no sistema de arquivos. Continue dessa maneira, adicionando
skip=10
a ao próximodd
e, em seguida, incrementando ofallocate
deslocamento inicial para-o 10GiB
. No final, adicione alguns caracteres nulos para preencher o arquivo tar final.Se o seu sistema de arquivos não suportar,
fallocate
você poderá fazer algo semelhante, mas começando no final do arquivo. Primeiro copie os últimos 10Gibytes do arquivo para um arquivo intermediário chamado, digamospart8
,. Em seguida, use otruncate
comando para reduzir o tamanho do arquivo original. Prossiga da mesma forma até ter 8 arquivos cada um com 10Gibyte. Você pode então concatenar o cabeçalho epart1
parabigarchive.tar
, em seguida, removerpart1
, e em seguida, concatenarpart2
e removê-lo, e assim por diante.fonte
A exclusão de um arquivo não faz necessariamente o que você pensa. É por isso que, em sistemas do tipo UNIX, a chamada do sistema é chamada
unlink
e nãodelete
. Na página do manual:Como conseqüência, enquanto o compressor / arquivador de dados estiver lendo o arquivo, ele permanecerá, ocupando espaço no sistema de arquivos.
fonte
Dado o contexto, interpretarei esta pergunta como:
Como remover dados do disco imediatamente após a leitura, antes da leitura do arquivo completo, para que haja espaço suficiente para o arquivo transformado.
A transformação pode ser qualquer coisa que você queira fazer com os dados: compactar, criptografar etc.
A resposta é esta:
Resumindo: leia dados, jogue-os no gzip (ou o que você quiser fazer com eles), armazene em buffer a saída, para que possamos ler mais do que escrevemos e escrevê-los novamente no arquivo. Esta é uma versão mais bonita e mostra a saída durante a execução:
Vou passar por isso, linha por linha:
cat "$file"
lê o arquivo que você deseja compactar. É um uso inútil de gato (UUOC), já que a próxima parte, pv, também pode ler o arquivo, mas acho isso mais bonito.Ele o canaliza para
pv
mostrar informações de progresso (-cN
diz 'use algum tipo de [c] ursor' e dê a [N] ame).Aqueles tubos nos
gzip
quais obviamente faz a compactação (leitura de stdin, saída para stdout).Isso entra em outro
pv
(exibição de canal).Isso entra
dd bs=$buffer iflag=fullblock
. A$buffer
variável é um número, algo como 50 megabytes. É a quantidade de RAM que você deseja dedicar ao manuseio seguro do seu arquivo (como ponto de dados, o buffer de 50 MB para um arquivo de 2 GB foi bom). Oiflag=fullblock
instruidd
a ler até$buffer
bytes antes de transmiti-lo. No início, o gzip escreverá um cabeçalho, portanto a saída do gzip será inserida nessadd
linha. Em seguidadd
, espere até que haja dados suficientes antes de transmiti-los, para que a entrada possa ler mais. Além disso, se você tiver peças descompactáveis, o arquivo de saída poderá ser maior que o arquivo de entrada. Esse buffer garante que, até$buffer
bytes, isso não seja um problema.Em seguida, entramos em outra linha de visualização de tubos e, finalmente, em nossa
dd
linha de saída . Esta linha temof
(arquivo de saída) econv=notrunc
especificada, ondenotrunc
indicadd
para não truncar (excluir) o arquivo de saída antes de gravar. Portanto, se você possui 500 bytesA
e escreve 3 bytesB
, o arquivo seráBBBAAAAA...
(em vez de substituído porBBB
).Não cobri as
2>/dev/null
peças e elas são desnecessárias. Eles apenas arrumam um pouco a saída suprimindodd
a mensagem "Eu terminei e escrevi tantos bytes". As barras invertidas no final de cada linha (\
) fazem com que o bash trate a coisa toda como um grande comando que se encaixa.Aqui está um script completo para facilitar o uso. Curiosamente, eu o coloquei em uma pasta chamada 'gz-in-place'. Percebi então o acrônimo que fiz: GZIP: gnu zip no local. Então, apresento GZIP.sh:
Eu sinto vontade de adicionar outra linha de buffer antes do gzip, para impedir que ele seja
dd
gravado muito longe quando a linha de buffer flui, mas com apenas 50MiB de buffer e 1900MB de/dev/urandom
dados, parece que já funciona de qualquer maneira (o md5sums correspondia após a descompactação). Relação boa o suficiente para mim.Outra melhoria seria a detecção de escrita muito longe, mas não vejo como fazer isso sem remover a beleza da coisa e criar muita complexidade. Nesse ponto, você também pode torná-lo um programa python completo que faz tudo corretamente (com falhas de segurança para impedir a destruição de dados).
fonte