Linux - impedindo que um aplicativo falhe devido à falta de espaço em disco

2

Devido a um cenário imprevisível, estou atualmente precisando encontrar uma solução para o fato de que um aplicativo (que não desejo matar) está ocupando lentamente todo o espaço em disco. Para dar mais contexto

  • Eu tenho um aplicativo em Python que usa multiprocessamento.Pool para iniciar 5 threads. Cada thread grava alguns dados em seu próprio arquivo.

  • O programa está sendo executado no Linux e eu não tenho acesso root à máquina.

  • O programa é intensivo da CPU e está em execução há meses. Ainda tem alguns dias para escrever todos os dados.

  • 40% dos dados nos arquivos são redundantes e podem ser removidos após um teste rápido.

  • O sistema no qual o programa está sendo executado tem apenas 30 GB de espaço em disco restante e, com a taxa atual de trabalho, ele certamente ficará sobrecarregado antes de o programa terminar.

Dados os pontos acima, vejo as seguintes soluções com os respectivos problemas

  • Dado que o número do processo i está gravando no arquivo_i, é seguro mover file_i para um local externo? O SO simplesmente criará uma nova instância de file_i e gravará nela? Eu suponho que mover o arquivo poderia removê-lo e o processo terminaria gravando em um arquivo "morto"?

  • Existe uma maneira de "linha de comando" para parar 4 dos 5 trabalhadores gerados e esperar até que um deles termine e então continue seu trabalho? (Tenho certeza de que um único thread de trabalho evitaria sobrecarregar o disco)

  • Suponha que eu use CTRL + Z para congelar o processo principal. Isso interromperá todos os outros processos gerados pelo multiprocessamento.Pool? Se sim, posso então editar com segurança os arquivos para remover as linhas redundantes?

Dadas as três opções que vejo, algum deles funcionaria nesse contexto? Se não, existe uma maneira melhor de lidar com esse problema? Eu realmente gostaria de evitar o cenário em que o programa falha poucos dias antes de terminar.

    
por Jernej 05.06.2014 / 16:14

3 respostas

2

Se você mover um arquivo para um sistema de arquivos diferente, o que acontece sob o capô é que o conteúdo atual do arquivo é copiado e o arquivo original é excluído. Se o programa ainda estava gravando no arquivo, ele continua gravando no arquivo agora excluído. Um arquivo deletado-mas-aberto, na verdade, não é apagado, mas apenas desanexado (não tem mais nome); o arquivo é excluído para real quando o programa o fecha. Então você pega o pior dos dois mundos: o arquivo ainda usa tanto espaço em disco, mas você perde o restante da saída.

Você pode pressionar Ctrl + Z para suspender o processo em primeiro plano e retomá-lo com o comando bg ou fg . Todos os tópicos são suspensos, a menos que o programa tenha passado por situações que se comportem de outra forma. (Um programa projetado para gerar filhos pela rede pode se comportar de outra forma. Um programa multithread de processo único tem alta probabilidade de se comportar normalmente.) Se o programa consistir em processos diferentes, use o comando ps para localizá-los todos e algo como kill -STOP 1234 1238 1239 para suspender todos eles (use kill -CONT … para continuá-los depois).

Se o programa gravar ou até mesmo ler no arquivo, você não poderá remover seus dados sob o seu nariz. Mover os dados nesse estágio pode ser factível, mas seria difícil e dependente de como o programa funciona. Mas, dada a sua descrição, o programa provavelmente continua anexando a cada arquivo, em cujo caso é possível remover alguns dados no início.

Não edite os arquivos: é improvável que isso seja feito. A maioria dos editores trabalha salvando um novo arquivo e movendo-o no lugar dos antigos (isso é mais robusto em caso de falha ao salvar). Você pode economizar espaço em disco truncando o início do arquivo. Primeiro, copie o arquivo para salvar os dados em outro lugar. Em seguida, trunque o arquivo para comprimento 0. O programa continuará anexando na posição onde estava antes; se essa posição for 12345, então, assim que o programa anexar outro byte, o arquivo será iniciado com 12345 bytes nulos. A maioria desses bytes nulos não ocupará espaço em disco: o arquivo será um arquivo esparso .

# Suspend the program first, otherwise you'll lose output produced between cp and truncation!
for x in *.out; do
  cp "$x" /elsewhere/
  : >|"$x"  # truncate $x to size 0
done

Quando o programa terminar, você poderá anexar os dados restantes aos arquivos salvos em outro lugar. O utilitário tail pode copiar um arquivo omitindo os primeiros N bytes; note que o argumento é um mais o número de bytes para omitir.

for x in *.out; do
  existing_size=$(stat -c %s "/elsewhere/$x")
  tail -c +$((existing_size+1)) "$x" >>"/elsewhere/$x"
done

Se você tiver o rsync 3.0.0 ou superior, poderá usar

rsync --append *.out /elsewhere/

Observe que as versões mais antigas do rsync sobrescreveriam a parte existente dos arquivos com os bytes nulos recém-aparecidos da origem! Verifique suas versões do rsync antes de fazer isso.

    
por 06.06.2014 / 03:54
1

Sem acesso root, suas opções são muito limitadas. Sua melhor aposta, e apenas a chance real de sucesso IMHO, é comprimir os arquivos que já foram escritos e fechados e espero que isso libere espaço suficiente para o seu programa para ser concluído. Pode haver outras opções disponíveis no pessoal do SO, você já tentou perguntar lá?

    
por 05.06.2014 / 16:24
1

Given that the process number i is writing to file_i, is it safe to move file_i to an external location? Will the OS simply create a new instance of file_i and write to it? I assume moving the file would remove it and the process would end up writing to a "dead" file?

Se o programa estiver constantemente abrindo o arquivo, gravando dados e fechando novamente, então sim, você pode simplesmente mover o arquivo e ele criará um novo. A maioria dos programas não funciona dessa maneira. É provável que o SO mostre que o arquivo foi movido, mas na verdade ocupa o espaço em disco até que o programa feche o identificador de arquivo.

Is there a "command line" way to stop 4 of the 5 spawned workers and wait until one of them finishes and then resume their work? (I am sure one single worker thread would avoid hogging the disk)

Dependeria exatamente de que tipo de threads de trabalho o programa usa, e você quase certamente precisaria de acesso root (você provavelmente teria que usar ferramentas de depuração, e a seqüência exata seria altamente dependente de como o programa funcionava) . Sem acesso à raiz e um conhecimento íntimo do funcionamento interno do programa, isso provavelmente é inviável.

Suppose I use CTRL+Z to freeze the main process. Will this stop all the other processes spawned by multiprocessing.Pool? If yes, can I then safely edit the files as to remove the redundant lines?

Depende novamente de como o programa está sendo executado. É provável que a suspensão do processo também suspenda os trabalhadores, mas não uma garantia. Eu não acredito que isso vai mudar o problema no entanto, como o ponteiro de arquivo do identificador de arquivo ainda apontará para o mesmo deslocamento que antes do arquivo foi editado.

Você pode mover outros arquivos para fora do sistema? Ou é uma VM onde você poderia expandir os discos virtuais?

    
por 05.06.2014 / 16:26