Excluindo bilhões de arquivos de um diretório enquanto observa o progresso também

35

Eu tenho um diretório de 30 TB com bilhões de arquivos que são formalmente todos os arquivos JPEG. Estou excluindo cada pasta de arquivos assim:

sudo rm -rf bolands-mills-mhcptz

Este comando apenas é executado e não mostra nada se está funcionando ou não.

Eu quero ver como está excluindo arquivos ou qual é o status atual do comando.

    
por Junaid Farooq 01.12.2016 / 11:24

6 respostas

28

Confira a resposta da lesmana , é muito melhor do que a minha - especialmente o último pv exemplo, que ganhou demorará muito mais tempo do que o original silencioso rm se você especificar /dev/null em vez de logfile .

Assumindo que o seu rm suporta a opção (provavelmente já que você está executando o Linux), você pode executá-lo no modo detalhado com -v :

sudo rm -rfv bolands-mills-mhcptz

Como foi apontado por vários comentaristas, isso pode ser muito lento devido à quantidade de saída sendo gerada e exibida pelo terminal. Você poderia redirecionar a saída para um arquivo:

sudo rm -rfv bolands-mills-mhcptz > rm-trace.txt

e veja o tamanho de rm-trace.txt .

    
por 01.12.2016 / 11:26
96

Você pode usar rm -v para ter rm imprimir uma linha por arquivo excluída. Dessa forma, você pode ver que rm está de fato trabalhando para excluir arquivos. Mas se você tiver bilhões de arquivos, tudo o que verá é que rm ainda está funcionando. Você não terá ideia de quantos arquivos já foram excluídos e quantos ainda restam.

A ferramenta pv pode ajudar você com uma estimativa de progresso.

link

Veja como você chamaria rm com pv com a saída de exemplo

$ rm -rv dirname | pv -l -s 1000 > logfile
562  0:00:07 [79,8 /s] [====================>                 ] 56% ETA 0:00:05

Neste exemplo inventado, eu disse a pv que há 1000 arquivos. A saída de pv mostra que 562 já foram excluídos, o tempo decorrido é de 7 segundos e a estimativa a concluir é de 5 segundos.

Algumas explicações:

  • pv -l faz com que pv conte por novas linhas em vez de bytes
  • pv -s number informa pv do total para poder dar uma estimativa.
  • O redirecionamento para logfile no final é para saída limpa. Caso contrário, a linha de status de pv será misturada com a saída de rm -v . Bônus: você terá um arquivo de log do que foi excluído. Mas cuidado, o arquivo ficará enorme. Você também pode redirecionar para /dev/null se não precisar de um log.

Para obter o número de arquivos, você pode usar este comando:

$ find dirname | wc -l

Isso também pode levar muito tempo se houver bilhões de arquivos. Você também pode usar pv aqui para ver quanto conta

$ find dirname | pv -l | wc -l
278k 0:00:04 [56,8k/s] [     <=>                                              ]
278044

Aqui diz que demorou 4 segundos para contar 278k arquivos. A contagem exata no final ( 278044 ) é a saída de wc -l .

Se você não quiser esperar pela contagem, poderá adivinhar o número de arquivos ou usar pv sem estimativa:

$ rm -rv dirname | pv -l > logfile

Assim você não terá nenhuma estimativa para terminar, mas pelo menos você verá quantos arquivos já foram deletados. Redirecione para /dev/null se você não precisa do arquivo de log.

Nitpick:

  • você realmente precisa de sudo ?
  • geralmente rm -r é suficiente para excluir recursivamente. não há necessidade de rm -f .
por 01.12.2016 / 12:49
22

Outra opção é observar o número de arquivos no sistema de arquivos diminuir. Em outro terminal, execute:

watch  df -ih   pathname

A contagem de inodes usados diminuirá à medida que rm avança. (A menos que os arquivos tenham muitos links, por exemplo, se a árvore foi criada com cp -al ). Isso rastreia o progresso da exclusão em termos de número de arquivos (e diretórios). df sem -i acompanhará em termos de espaço usado.

Você também pode executar iostat -x 4 para ver operações de E / S por segundo (assim como o kiB / s, mas isso não é muito relevante para E / S de metadados puros).

Se você ficar curioso sobre quais arquivos rm está trabalhando no momento, poderá anexar um strace a ele e observar como as chamadas do sistema unlink() (e getdents) são emitidas em seu terminal. por exemplo. %código%. Você pode sudo strace -p $(pidof rm) o strace se separar de ^c sem interrompê-lo.

Eu esqueço se rm altera o diretório para a árvore que está excluindo; se assim você poderia olhar para rm -r . Seu /proc/<PID>/cwd pode freqüentemente ter um diretório fd aberto, então você pode ver o que o processo /proc/<PID>/fd está vendo no momento.

    
por 02.12.2016 / 02:22
4

Embora todas as respostas acima usem rm , rm pode realmente ser muito lento na exclusão de um grande número de arquivos, como observei recentemente ao extrair arquivos de ~ 100K de um arquivo .tar na verdade levou menos tempo do que excluí-los . Embora isso realmente não responda à pergunta que você fez, uma solução melhor para o seu problema pode ser usar um método diferente para excluir seus arquivos, como uma das respostas com votos para esta questão .

Meu método favorito é usar rsync -a --delete . Acho que esse método é rápido o suficiente para valer a facilidade de uso em a resposta mais votada para essa pergunta , em que o autor escreveu um programa em C que você precisaria compilar. (Observe que isso produzirá todos os arquivos sendo processados para stdout, bem como rm -rv ; isso pode retardar o processo em uma quantidade surpreendente. Se você não quiser essa saída, use rsync -aq --delete ou redirecione a saída para um arquivo .)

O autor dessa resposta diz:

The program will now (on my system) delete 1000000 files in 43 seconds. The closest program to this was rsync -a --delete which took 60 seconds (which also does deletions in-order, too but does not perform an efficient directory lookup).

Eu descobri que isso é bom o suficiente para meus propósitos. Também é potencialmente importante a partir dessa resposta, pelo menos se você estiver usando o ext4:

As a forethought, one should remove the affected directory and remake it after. Directories only ever increase in size and can remain poorly performing even with a few files inside due to the size of the directory.

    
por 03.12.2016 / 04:37
3

Uma coisa que você poderia fazer seria iniciar o processo rm em segundo plano (sem saída, para que não seja retardado) e, em seguida, monitorá-lo em primeiro plano com um simples ( a) comando:

pax> ( D=/path/to/dir ; rm -rf $D & while true ; do
...>   if [[ -d $D ]] ; then
...>     echo "$(find $D | wc -l) items left"
...>   else
...>     echo "No items left"
...>     break
...>   fi
...>   sleep 5
...> done )

27912 items left
224 items left
No items left

pax> _

A combinação find/wc pode ser substituída por qualquer ferramenta capaz de fornecer as unidades desejadas.

(a) Bem, relativamente simples, comparado a, digamos, física nuclear, a hipótese de Riemann, ou o que comprar minha esposa para o Natal: -)

    
por 03.12.2016 / 05:11
0

Há algum tempo, escrevi algo para imprimir a taxa em que as linhas foram impressas. Você pode executar rm -rfv | ./counter e imprimir linhas por segundo / min. Embora não seja um progresso direto, ele lhe dará algum feedback sobre a taxa de progresso, talvez o rm tenha entrado em um sistema de arquivos de rede ou similar, talvez?

Link para o código está aqui:

link

    
por 25.02.2017 / 17:14