Como tornar o `rm` mais rápido no ext3 / linux?

32

Eu tenho o sistema de arquivos ext3 montado com opções padrão. Nele, tenho alguns arquivos de ~ 100 GB.

A remoção de qualquer um desses arquivos leva muito tempo (8 minutos) e causa muito tráfego io, o que aumenta a carga no servidor.

Existe alguma maneira de tornar a empresa não tão perturbadora?


fonte
4
Basicamente, nenhum método daqui funcionou, então desenvolvemos o nosso. Descreve-o aqui: depesz.com/index.php/2010/04/04/how-to-remove-backups

Respostas:

14

A resposta mais interessante foi originalmente enterrada em um comentário sobre a pergunta. Aqui está como resposta de primeira classe para torná-lo mais visível:

Basicamente, nenhum método daqui funcionou, então desenvolvemos o nosso. Descreve-o aqui: http://www.depesz.com/index.php/2010/04/04/how-to-remove-backups/ - depesz

Esse link é uma análise incrivelmente completa da exploração e descoberta de uma solução viável.

Observe também:

O artigo diz:

Como você pode ver, usei -c2 -n7opções para ionice, que parecem sãs.

o que é verdade, mas o usuário TafT diz que, se você não deseja interrupções, o -c3'inativo' seria uma escolha melhor do que o -c2'melhor esforço'. Ele costumava -c3criar em segundo plano e descobriu que funcionava bem sem fazer com que a construção esperasse para sempre. Se você realmente tiver 100% de uso io, -c3não permitirá que a exclusão seja concluída, mas ele não espera que seja isso que você baseou no teste realizado.

Matt McClure
fonte
18

Atualize para ext4 ou algum outro sistema de arquivos moderno que utilize extensões. Como o ext3 usa o esquema de blocos indiretos em vez de extensões, a exclusão de arquivos grandes inevitavelmente envolve muito trabalho.

janneb
fonte
6

Você pode experimentar o ionice . Não vai torná-lo mais rápido, mas pode torná-lo menos perturbador.

Pausado até novo aviso.
fonte
4

Em termos de eficiência, o uso de uma rm por arquivo não é ideal, pois requer um fork e exec para cada rm.

Supondo que você tenha um list.txt contendo os arquivos que deseja remover, isso seria mais eficiente, mas ainda será lento:

xargs -i rm {} < list.txt

Outra abordagem seria: nice -20 xargs -i rm {} < list.txt
(isso levará menos tempo, mas afetará bastante o seu sistema :)

ou

Eu não sei o quão rápido isso seria, mas:

mv <file-name> /dev/null 

ou

Crie um ponto de montagem especial com um sistema de arquivos rápido (usando um dispositivo de loop?), Use isso para armazenar e excluir seus arquivos enormes.
(talvez mova os arquivos para lá antes de excluí-los, talvez seja mais rápido ou apenas desmonte quando quiser que os arquivos sejam removidos)

ou

cat /dev/null > /file/to/be/deleted(portanto, é de tamanho zero agora) e se você quiser que desapareça rm -rf <file>agora

ou melhor ainda

largar o gato e apenas fazer # > /file/to/be/emptied


fonte
bem, estou removendo 1 arquivo, para que não haja sobrecarga.
stackoverflow.com/questions/1795370/… - verifique isso também #
1

Eu tive problemas para obter o diretório para excluir em um ritmo razoável, o processo estava bloqueando o disco e criando um monte de processos tentando acessar o disco. O ionice não funcionou, apenas continuou a usar 99% da IO do disco e bloqueou todos os outros processos.

Aqui está o código Python que funcionou para mim. Exclui 500 arquivos de cada vez, faz uma pausa de 2 segundos para permitir que os outros processos façam seu trabalho e continua. Funciona bem.

import os, os.path
import time

for root, dirs, files in os.walk('/dir/to/delete/files'):
    file_num = 0
    for f in files:
        fullpath = os.path.join(root, f)
        os.remove(fullpath)
        if file_num%500 == 1:
            time.sleep(2)
            print "Deleted %i files" % file_num
        file_num = file_num + 1
Nick Woodhams
fonte
1
Experimente em arquivos 100G + no sistema de arquivos ext3. O problema está no tamanho de um único arquivo, não no número de arquivos.
No seu caso, parece que não funcionaria. Mas eu tinha uma tonelada de arquivos pequenos. Obrigado pelo feedback.
Nick Woodhams
1

Meus dois centavos.

Eu já tenho esse problema. "Em scripts seqüenciais que precisam ser executados rapidamente, o processo remove muitos arquivos". Portanto, o "rm" fará com que a velocidade do script se aproxime do tempo de espera / execução de E / S.

Então, para tornar as coisas mais rápidas, adicionei outro processo (script bash) iniciado por cron .. como um coletor de lixo, ele remove todos os arquivos em um diretório específico.

Atualizei o script original substituindo o "rm" por um mv para uma "pasta de lixo" (renomeie o arquivo adicionando um contador no final de seu nome para evitar colisões).

Isso funciona para mim, o script é executado pelo menos três vezes mais rápido. mas funcionará bem apenas se a pasta de lixo e o arquivo original estiverem no mesmo ponto de montagem (mesmo dispositivo) para evitar a cópia do arquivo. (mv no mesmo dispositivo consome menos IO que rm)

Espero que ajude ..

Emmanuel Devaux
fonte
0

Observe também que a resposta de Dennis Williamson, que sugere a ionice como uma solução alternativa para a carga, funcionará apenas se o seu dispositivo de bloco usar o agendador CFQ io.

famzah
fonte
0

Você pode tentar criar um sistema de arquivos em loop para armazenar seus backups.

# dd if=/dev/zero of=/path/to/virtualfs bs=100M count=1024 # 100 MB * 1024 = 100 GB
# mke2fs /path/to/virtualfs
# mount -t ext2 /path/to/virtualfs /mnt/backups -o loop

Então, quando você deseja limpar os backups:

# umount /mnt/backups
# mke2fs /path/to/virtualfs
# mount -t ext2 /path/to/virtualfs /mnt/backups -o loop

Presto! Todo o sistema de arquivos virtual é limpo em questão de momentos.

anfetamaquina
fonte
não resolve o problema, pois só funcionaria se eu quisesse remover todos os backups em um sistema de arquivos fornecido.
0

Você pode usar multithread com xargs

find . -type f | xargs -P 30 rm -rf 

onde 30 é o número de threads que você deseja criar. Se você estiver usando zero, o sistema criará o máximo de encadeamentos disponíveis para o usuário que está executando a tarefa.

Juan Carlos
fonte
1
findtem uma -deleteopção que é uma alternativa muito melhor.
Ariel #
0

mv <nome do arquivo> / dev / null

/ dev / null é um arquivo, não um diretório. Não é possível mover um arquivo para um arquivo ou corre o risco de substituí-lo.

Crie um ponto de montagem especial com um sistema de arquivos rápido (usando um dispositivo de loop?), Use isso para armazenar e excluir seus arquivos enormes. (talvez mova os arquivos para lá antes de excluí-los, talvez seja mais rápido ou apenas desmonte quando quiser que os arquivos sejam removidos)

Eu não acho isso prático. Usaria desnecessariamente mais E / S do que o OP gostaria.

Felipe Alvarez
fonte
-1

/ dev / null é um arquivo, não um diretório. Não é possível mover um arquivo para um arquivo ou corre o risco de substituí-lo.

Na verdade, é um dispositivo e todos os dados gravados nele são descartados, então mv <file> /dev/nullfaz sentido

Da Wikipedia, a enciclopédia livre
Nos sistemas operacionais do tipo Unix, / dev / null ou o dispositivo nulo é um arquivo especial que descarta todos os dados gravados nele (mas relata que a operação de gravação foi bem-sucedida) e não fornece dados para nenhum processo que lê a partir dele (produzindo EOF imediatamente). [1]


fonte
1
Isso está errado e incrivelmente perigoso. / dev / null é um dispositivo, que é um objeto especial parecido com um arquivo. Se você é root, "mv / some / file / dev / null" DELETE o dispositivo / dev / null especial e moverá seu arquivo para lá! Portanto, na próxima vez que alguém tentar usar / dev / null, usará um arquivo real em vez do dispositivo, e ocorrerá um desastre. (Quando a Wikipedia diz que "descarta todos os dados gravados nele", isso significa que "cat / some / file> / dev / null" lerá / some / file e descartará os dados que você ler, mas isso não afetará o arquivo original).
user9876