bash travou com loop [duplicado]

6
    

Esta pergunta já tem uma resposta aqui:

    
  •              Falha na expansão do 'seq' e do bash                                      1 resposta                          
  •     

A questão pode ser trivial, mas com este simples for loop

for i in {1..10000000}; do echo "$i" line >> file
done

meu shell falhou após algum tempo de elaboração (a guia no emulador de terminal foi fechada automaticamente) e file não foi criado.

É GNU bash, version 4.1.11(2)-release .

Isso é devido a um limite de memória ou o que mais? E se sim qual deve ser esse limite?

Com {1..1000000} funcionou corretamente.

    
por BowPark 05.09.2014 / 13:13

2 respostas

7

Isso acontece porque os colchetes são expandidos antes que o comando seja chamado. Assim você acaba com um comando como:

for i in 1 2 3 ... 10000000 ; do ... 

.. e, portanto, usa muita memória ou trava.

A solução ao trabalhar com loops longos é usar a sintaxe do estilo c do bash:

for ((i = 1; i <= 10000000; i++))
do 
    ...
done

Ou, se você quiser permanecer compatível com outros shells, pode canalizar para um loop while:

seq 1 10000000 | while IFS= read -r line
do
     ...
done
    
por 05.09.2014 / 13:47
3

Meu processo bash executando este comando requer muita memória, sim. 1.9GB no meu caso (x86_64). Você pode ter encontrado o seu limite e o assassino de falta de memória do kernel o removeu. Para mim, funciona. Demora cerca de 3 minutos

 $ wc -l file
 10000000 file
 $ tail -n1 file
 10000000 line
 $ ls -hl file
 -rw-r--r-- 1 seb users 123M Sep  5 13:19 file

Para confirmar a hipótese de limitação de RAM: Se você tiver swap, poderá tentar vê-lo sendo preenchido. Use, e. htop para isso.

Se eu aumentar ainda mais o loop de mais de 100.000.000 de elementos, o processo também consome dez vezes mais RAM: 18GB .

@ user000001 fornece uma explicação e uma alternativa. Eu testei com a sintaxe do estilo C (que ele forneceu):

for ((i = 1; i <= 10000000; i++))
do 
 ...
done

Este processo não requer mais RAM do que um processo bash regular.

    
por 05.09.2014 / 13:21