2012-01-09 2 views
0

В bash Мне нужно запустить скрипт, который проходит от i = 1 до i = 99999999, но он всегда заканчивается из памяти. Есть ли обходной путь? или существует максимальное значение для i?Bash Script Loop Out of Memory?

first=1 
last=99999999 
randomString="CXCXQOOPSOIS" 

for val in $(seq $first $last) 
do 
    padVal=$(printf "%010d\n" $val) 
    hash=$(echo -n $randomString$padVal | md5sum) 
    if [[ "$hash" =~ ^000000) ]]; then 
    echo "Number: $val" >> log_000000 
    echo "$val added to log - please check." 
    fi 
done 
+2

Что находится внутри цикла? Я предполагаю, что он не пуст? –

+0

Кажется, что цикл выделяет новую память для каждого цикла, а общий размер выделенной памяти достигает системного предела, это не дает вам конкретного совета, не видя кода цикла. – sll

+0

для значений i, я фактически добавляю его к строке, а затем md5 hash it. когда появляется хеш с выражением^123123, я хочу выйти из цикла. –

ответ

5

bash обеспечивает C-подобный синтаксис for цикл:

first=1 
last=99999999 
randomString="CXCXQOOPSOIS" 

for ((val=$first; val<$last; val++)) 
do 
    padVal=$(printf "%010d\n" $val) 
    hash=$(echo -n $randomString$padVal | md5sum) 
    if [[ "$hash" =~ ^000000) ]]; then 
    echo "Number: $val" >> log_000000 
    echo "$val added to log - please check." 
    fi 
done 
+0

будет ли это лучше, память мудрая? –

+1

Да, намного лучше; он генерирует одно число за раз, а не 100 миллионов. –

+0

спасибо за совет. просто начал работать с shell-скриптами и немного повеселился! –

1

Ваша команда seq генерирует 100 млн номеров (бар пару) и требует 800 МиБ или так памяти для хранения только список цифр (вероятно, занижена, каждое число может быть проведен в отдельной памяти распределение, которое может означать 8 байтов для указателя и 16 байтов для выделенного блока, что утроит оценку пространства памяти).

Вы можете улучшить положение вещей резко помощью:

for millions in $(seq 0 99) 
do 
    for smallstuff in $(seq -f "%6.0f" 0 999999) 
    do 
     val="$millions$smallstuff" 
     ... 
    done 
done 

Это значительно уменьшает объем памяти, необходимой; единственная проблема для просмотра - то, что он проверяет 0, который не был у вашего исходного кода.

+0

что делает линию для миллионов в $ (далее-99) делать? –

+0

Он генерирует строки от 0 до 99 (сто строк длиной не более двух символов). На самом деле вы, вероятно, захотите использовать: 'для миллионов в" "$ (seq 1 99)' для создания пустого префикса. Кроме того, внутренний цикл генерирует ведущие нули на малом материале; если это имеет значение, вы должны быть немного более осторожны, но основная идея разбить цикл, чтобы вы не генерировали 100 миллионов строк в начале, все еще стоит. –

+0

Благодарим вас за объяснение! –

1

Если вы все еще хотите использовать seq=> поэтому отделить seq и петлю с помощью pipe: |
Это решение является более портативным и может использоваться на других оболочках.
Печать памяти по-прежнему снижается, но для этого сценария требуется обработать два потока.

first=1 
last=99999999 
randomString="CXCXQOOPSOIS" 

seq $first $last | 
while read val 
do 
    padVal=$(printf "%010d\n" $val) 
    hash=$(echo -n $randomString$padVal | md5sum) 
    if [[ "$hash" =~ ^000000) ]]; then 
    echo "Number: $val" >> log_000000 
    echo "$val added to log - please check." 
    fi 
done 
+0

Мне не обязательно использовать seq, будет ли c-образный цикл лучше? –

+0

Петля C, вероятно, лучший вариант; это действительная альтернатива. Оба лучше, чем мое решение, хотя мой диагноз причины проблемы стоит. –