Согласно исходному коду , невозможно сделайте это с помощью top.
Тем не менее, top имеет параметр -p
, который позволяет указать ему, что нужно отслеживать только определенные PID. К сожалению, этот параметр также ограничен 20 параметрами, и в ядре легко может быть запущено более 20 процессов.
Я создал двухстрочный сценарий, чтобы проверить это:
kprocs=$(ls -l /proc/*/exe | grep -v " -> " | cut -d "/" -f 3)
top -c -p $(echo ${kprocs} | sed 's/ /,/g')
Если вы блуждаетесь, я обнаруживаю процессы ядра, глядя, какие ссылки не указывают на двоичный файл на диске.
В первый раз в вашем цикле вы устанавливаете energy=( $(awk...) )
, и вывод из awk
состоит из нескольких строк, каждая из которых содержит одно число и заканчивается символом новой строки, как это всегда делают строки в Unix. Подстановка команд $(... )
удаляет завершающую новую строку (с ), а когда она не заключена в двойные -кавычки, то разбивает результат на «слова» в любой из пробелов на новой строке (у вас есть новые строки ), и, наконец, если какое-либо слово является «шаблоном» (, содержащим ?*[..]
), которое соответствует любому имени файла (s ), оно заменяется этими именами файлов (s )как отдельные «слова» (у вас нет таких шаблонов 'glob' ). Назначение массива energy=(... )
затем сохраняет эти слова как элементы массива.
Во второй раз через IFS устанавливается запятая. Теперь, когда $(... )
пытается разбить на слова, он использует (только запятую )и в выводе awk нет запятых, поэтому весь вывод (, включая новые строки ), остается как одно слово и присваивается массиву как один элемент.
Вам необходимо возвращать IFS для каждой итерации. Кроме того, вам необходимо установить стандартное значение IFS или, по крайней мере, значение, содержащее новую строку, в записи этого скрипта. OTOH откат IFS непосредственно перед выходом из скрипта в основном бесполезен; сценарий обычно запускается в отдельном процессе оболочки, и любые настройки переменных или другие изменения процесса -, сделанные сценарием, отбрасываются при выходе из сценария.
Или , вместо изменения IFS и явного возврата, вы можете сделать это в подоболочке , чтобы изменение отбрасывалось после завершения подоболочки. Синтаксис оболочки для подоболочки: также круглые скобки, на этот раз сами по себе:
( IFS=","; echo "${energy[*]};" >> $energies )
# you don't actually need to quote, here but
# it's a good habit for string literals in general
Также в целом printf
безопаснее, чем echo
, потому что в зависимости от используемой оболочки и/или системы echo
может исказить некоторые строковые значения. Однако значения, которые вы здесь --ограничены десятичными числами --, безопасны для echo
.
Для bash есть еще одна возможность обрабатывать данные как одну строку, а не как массив:
energy=$( awk '/Total energy/{print $3}' output )
# command substitution strips the last newline
# scalar assignment does NOT do wordsplit and glob
echo "${energy//$'\n'/,};" >>energies_blah
# replaces all other newlines with commas, and adds semicolon
echo "${energy##*$'\n'}" >>final_energies_blah
# removes everything up to and including the last newline,
# leaving only the last number
Или вы можете выполнять всю работу с помощью awk, особенно не -древнего GNU awk с 'endfile':
# read simcount,simend and set energies,fenergies
infiles=$( printf 'sim%d/output ' $( seq $simcount $simend ) )
awk -vf1=$energies -vf2=$fenergies '/Total Energy/ {e=e","$3; f=$3} ENDFILE {print substr(e,2)";">>f1; print f>>f2; e=f=""}' $infiles
С другими awk вы можете сделать то же самое с немного более уродливым кодом (сначала! )проверка FNR==1&&NR>1
конца каждого файла, кроме последнего, и (где угодно)END
конца последнего файла.