Tenho 200 GB de espaço livre em disco, 16 GB de RAM (dos quais ~ 1 GB é ocupado pelo desktop e pelo kernel) e 6 GB de swap.
Eu tenho um SSD externo de 240 GB, com 70 GB usados 1 e o restante livre, do qual preciso fazer backup no meu disco.
Normalmente, eu faria dd if=/dev/sdb of=Desktop/disk.img
o disco primeiro e depois o compactaria, mas fazer a imagem primeiro não é uma opção, pois isso exigiria muito mais espaço em disco do que eu tenho, mesmo que a etapa de compactação resulte em espaço livre sendo compactado para que o arquivo final pode caber facilmente no meu disco.
dd
grava em STDOUT por padrão e gzip
pode ler de STDIN, portanto, em teoria, eu posso escrever dd if=/dev/sdb | gzip -9 -
, mas gzip
leva muito mais tempo para ler bytes do que dd
produzi-los.
De man pipe
:
Os dados gravados na extremidade de gravação do pipe são armazenados em buffer pelo kernel até serem lidos na extremidade de leitura do pipe.
Visualizo um |
como sendo um tubo real - um aplicativo inserindo dados e o outro retirando dados da fila do tubo o mais rápido possível.
E quando o programa no lado esquerdo grava mais dados mais rapidamente do que o outro lado do canal pode esperar processá-los? Isso causará extrema utilização de memória ou troca, ou o kernel tentará criar um FIFO no disco, preenchendo o disco? Ou apenas falhará SIGPIPE Broken pipe
se o buffer for muito grande?
Basicamente, isso se resume a duas perguntas:
- Quais são as implicações e os resultados de colocar mais dados em um canal do que os lidos de cada vez?
- Qual é a maneira confiável de compactar um fluxo de dados em disco sem colocar todo o fluxo de dados não compactado no disco?
Nota 1: Não posso simplesmente copiar exatamente os primeiros 70 GB usados e espero obter um sistema ou sistema de arquivos em funcionamento, devido à fragmentação e outras coisas que exigirão que todo o conteúdo esteja intacto.
fonte
lzop
vez degzip
; ele comprime muito mais rápido com apenas uma taxa de compressão ligeiramente mais baixa. Acho ideal para imagens de disco em que a velocidade de compactação pode ser um gargalo real.Respostas:
Tecnicamente, você nem precisa de
dd
:Se você fizer uso
dd
, você deve sempre ir com maior do que blocksize padrão comodd bs=1M
ou sofrer o inferno syscall (dd
's de bloco padrão é de 512 bytes, uma vez queread()
s ewrite()
s isso é4096
syscalls porMiB
, muita sobrecarga).gzip -9
usa muito mais CPU com muito pouco para mostrar. Segzip
você está atrasando, diminua o nível de compactação ou use um método de compactação diferente (mais rápido).Se você estiver fazendo backups baseados em arquivos em vez de
dd
imagens, poderá ter alguma lógica que decida se deseja compactar ou não (não há sentido em fazer isso para vários tipos de arquivos).dar
(tar
alternativa`) é um exemplo que possui opções para isso.Se o seu espaço livre for ZERO (porque é um SSD que retorna zero de forma confiável após TRIM e você executou
fstrim
e eliminou caches), você também pode usardd
comconv=sparse
sinalizador para criar uma imagem esparsa, descompactável e montável em loop, que usa espaço em disco zero para as áreas zero . Requer que o arquivo de imagem seja apoiado por um sistema de arquivos que suporte arquivos esparsos.Alternativamente, para alguns sistemas de arquivos, existem programas capazes de exibir apenas as áreas usadas.
fonte
dd bs=1M
" - Você pode, mas não espera muito. No meu PC,dd
fará cerca de 2 GB / s com blocos de 512 bytes. Esse não será o gargalo;gzip
será.dd
usa 2 GB / s com blocos de 512 bytes, ficaria surpreso se não atingisse o máximo de 100% de um núcleo de CPU no processo. Agora, se sua caixa é um quadcore que fica ocioso de qualquer maneira, você pode não notar a diferença. Todo mundo ainda faz, no entanto.dd
tamanho do bloco é mencionado, as pessoas aparecem.gzip
ser intensivo em CPU também fazia parte da minha resposta, ok? E desculpe, eu discordo de "insignificante". Ele pode adicionar apenas 1-2s por show comgzip -9
(mas isso ainda equivale a minutos ao processar centenas de shows), mas seguindo seu conselholzop -1
, é 1s por show vs. 4s por show. Testado em uma batata (vserver single core). A adição de um tamanho de bloco saudáveldd
não custa nada e tem zero desvantagens. Não escolha. Apenas faça. ymmvdd
lê e grava dados um bloco de cada vez e só possui um bloco pendente. tãomostra que
dd
usa aproximadamente 1 MB de memória. Você pode brincar com o tamanho do bloco e soltarvalgrind
, para ver o efeito nadd
velocidade do bloco .Quando você entra
gzip
,dd
simplesmente diminui a velocidade para correspondergzip
à velocidade. Seu uso de memória não aumenta, nem faz com que o kernel armazene os buffers no disco (o kernel não sabe como fazer isso, exceto por troca). Um cano quebrado só acontece quando uma das extremidades do cano morre; vejasignal(7)
ewrite(2)
para detalhes.portanto
é uma maneira segura de fazer o que você procura.
Ao canalizar, o processo de gravação acaba sendo bloqueado pelo kernel, se o processo de leitura não estiver em andamento. Você pode ver isso executando
Você verá que
dd
lê 1 MB e, em seguida, emite umwrite()
que fica lá, aguardando um minuto enquantosleep
é executado. É assim que os dois lados de um pipe se equilibram: o kernel bloqueia as gravações se o processo de gravação for muito rápido e as leituras se o processo de leitura for muito rápido.fonte
dd
sabe diminuir a velocidade para correspondergzip
à velocidade? É automático, como no kernel, ou calcula a partir de metadados sobre seu descritor de arquivo de saída?dd
chamadaswrite()
para colocar dados no canal.write()
na verdade transfere o controle para o kernel para que ele possa manipular a memória do pipe. Se o kernel vê que o tubo está cheio, ele espera ("bloco") até que o tubo tenha espaço suficiente. Somente então awrite()
chamada terminará e transferirá o controle de volta paradd
, que gravará dados no canal novamente.Não há implicações negativas além do desempenho: o canal possui um buffer, que geralmente é de 64 K; depois disso, uma gravação no canal simplesmente bloqueia até
gzip
ler mais alguns dados.fonte
Respondendo à pergunta real de como funciona: "e se o programa no lado esquerdo gravar mais dados mais rapidamente do que o outro lado do canal pode esperar processá-los?"
Isso não acontece. Há um buffer de tamanho limitado bastante pequeno no tubo; veja Qual é o tamanho do buffer do pipe?
Quando o buffer do pipe estiver cheio, o programa de envio será bloqueado . Quando faz uma chamada de gravação, o kernel não retornará o controle ao programa até que os dados tenham sido gravados no buffer. Isso fornece ao CPU o programa de leitura para esvaziar o buffer.
fonte
Talvez você só precise dos arquivos e use tar. Você pode preencher com zeros os blocos que não contêm o que quiser, alguém já perguntou sobre isso. Limpar espaço não utilizado com zeros (ext3, ext4)
Então, há o
pigz
que geralmente é mais rápido quegzip
.fonte