2012-05-30 5 views
1

У меня есть этот код:Почему мой код не работает так, как я его хочу?

total=0; 
ps -u $(whoami) --no-headers | awk {'print $1'} | while read line; 
          do vrednost=$(pmap $line | tail -n1 | column -t | cut -d" " -f3 | tr "K" " "); 
          total=$((vrednost + total)) 
          echo $total 
          done 
          echo total: $total 

Как вы можете видеть, мой код суммы использования всех моих процессов. Когда я повторяю свое общее количество каждый раз, пока он работает нормально, но в конце ... Когда я хочу, чтобы сумма была значением (echo total: $total), она все равно равна нулю. но до (в while) имеет правильное значение.

+0

не ответ на вашу проблему, но вы можете объявить 'total' иметь атрибут«целое», используя' -i объявить общее = 0', то просто скажите 'total + = $ vrednost'. – chepner

+0

@chepner: вы также можете сделать '((total + = vrednost))' с объявлением или без объявления переменной как целого. Для меня это делает ясно, что вы имеете в виду добавление, а не конкатенацию. –

ответ

0

Попробуйте

#!/bin/bash 
total=0; 
for line in `ps -u $(whoami) --no-headers | awk {'print $1'}`; 
do 
    vrednost=$(pmap $line | tail -n1 | column -t | cut -d" " -f3 | tr "K" " "); 
     total=$(($vrednost + $total)) 
     echo $total 
done 
echo "total: $total" 
+0

ps -u $ (whoami) - нет-заголовки | awk {'print $ 1'}; это говорит о том, что у этой ошибки есть ... я не знаю, как это исправить:/ – Blaz

+0

OH YEAH ---- it's working i fogot '' – Blaz

+0

спасибо большое! – Blaz

0

Давайте сократить количество дополнительных процессов, которые необходимо :)

declare -i total=0 
for size in $(ps -u $(whoami) --no-header -o vsz); do 
    total+=$size 
done 
echo $total 

Во-первых, использовать различные варианты ps для создания желаемый список размеров процесса, в килобайтах. Перейдем через этот список, используя bash for-loop, сохраняя общее количество в параметре, объявленном с атрибутом «integer» для легкой арифметики. Желаемая сумма теперь находится в total, готова для любого использования, которое вам нужно. Сумма включает в себя память, используемую самим процессом ps.

Использование while (предложения Дениса) и избежать процесса замещения (предложение Уильяма):

ps -u $(whoami) --no-header -o vsz | { 
    while read -r var; do 
    ((total+=$var)) 
    done 
    echo $total 
} 

(Для реального однострочника, вот dc команды, которую я позаимствовал из https://stackoverflow.com/a/453290/1126841:

ps -u $(whoami) --no-header -o vsz | dc -f - -e '[+z1<r]srz1<rp' 

Эта сумма включает в себя информацию, используемую командами ps и dc.)

+0

В большинстве случаев неверно использовать 'for' для итерации по замене команд. Из-за этого хорошо иметь привычку использовать 'while read -r var' вместо этого. –

1

Хорошо, выберите. Вы можете сделать это в BASH или AWK, но не делайте того и другого. Вы уже видели пример BASH, вот пример AWK:

ps -e -o user -o vsz | awk -v USER="$(whoami)" ' 
    BEGIN {TOTAL = 0} 
    END {print "Total is " TOTAL} 
    { 
     if ($1 == USER) { 
      TOTAL += $2 
     } 
    } 
' 

Awk, как язык программирования, который принимает на себя петлю (как perl -n) и обрабатывает каждую строку в файле. Каждое поле (обычно разделенное пробелами) задается переменной $. Первый $1, второй $2 и т.д.

Опция -v позволяет мне определить переменную AWK (в данном случае USER), прежде чем я бегу AWK.

Строка BEGIN - это то, что я хочу сделать, прежде чем запускать сценарий awk. В этом случае инициализируйте TOTAL до нуля. (ПРИМЕЧАНИЕ. Это действительно не обязательно, так как неопределенным переменным автоматически присваивается значение 0). Линия END - это то, что я хочу сделать потом. В этом случае распечатайте мою итоговую сумму.

Итак, если первое поле ($ 1) равно моему пользователю, я добавлю второе поле (vsize) к моему итогу.

Все программы Awk окружены {...}, и они обычно имеют одинарные кавычки вокруг них, чтобы предотвратить интерполяцию оболочки $1 и т. Д.

+1

Для удобства чтения я предпочитаю поместить блок 'END' в конец .... Кроме того, нет необходимости в операторе 'if' - поставьте свое условие вне скобок основного блока:' $ 1 == USER {TOTAL + = $ 2} ' –

+1

+1, но обратите внимание, что нет реальной необходимости для BEGIN. Просто используйте 'TOTAL + 0' в END, чтобы напечатать' 0', а не пустую строку. Переменные autovivified равны 0. –

+0

Мне нравится положить блок BEGIN и блок END в начале, чтобы люди увидели их. В противном случае люди пропускают их. Да, это больше кода, чем нужно. Однако я хотел подчеркнуть часть языка. Awk - это язык программирования с множеством функций. Я мог бы упростить все это с помощью одного лайнера: 'ps -u $ (whoami) --no-header -o vsz | awk 'END {print "Total is TOTAL} {TOTAL + = $ 1}'', но я снова хотел подчеркнуть язык Awk. –

0

Ответ Игнасио в порядке, но замена процесса не переносима. И есть более простое решение. Вы должны повторить итог в том же подоболочки, в котором она рассчитывается:

... | { while read line; do ...; done; echo total: $total; } 
Смежные вопросы