LINUX.ORG.RU

grep и кеширование

 ,


0

1

Есть программа, которая иногда ест много памяти. Потребление памяти ею можно отслеживать командой top -b -d60 -o +%MEM -c | grep memory_eater | grep -v grep > memory.log & disown Но иногда она быстро отрабатывает – за несколько минут, и файл остаётся пустой. В чём проблема? Слишком малый объём текста зависает в кеше и не сбрасывается? Можно ли как-то ускорить сбрасывание?

P.S. Если увеличить частоту опроса top до -d1 или -d0.1, всё важное фиксируется, но лог увеличивается на 2-3 порядка. Реально достаточно писать раз в минуту. Вопрос не в том, как отслеживать память, а как записать этот лог в файл.

Ответ:

top -b -d60 -o +%MEM -c | grep --line-buffered memory_eater | grep -v --line-buffered grep > memory.log & disown

или

top -b -d60 -o +%MEM -c | stdbuf -o0 -i0 grep memory_eater | stdbuf -o0 -i0 grep -v grep > memory.log & disown
★★★

Последнее исправление: olegd (всего исправлений: 2)

Ответ на: комментарий от mrjaggers

Проблема не в том, как узнать потребление памяти, а как записать текст в файл.

olegd ★★★
() автор топика
Ответ на: комментарий от pfg

кажись здесь grep & disown
& - отправка выполнения команды (grep) в фон.

наверн с && спутал. вот он аккурат используется как AND между командами.

Всё нормально работает, если поставить маленький интервал, вроде -d0.1

olegd ★★★
() автор топика
Ответ на: комментарий от mrjaggers

Где по этой ссылке написано, как с заданной частотой брать объём памяти и время работы процесса и сохранять в файл так, чтобы информация была видна уже с первой записи?

olegd ★★★
() автор топика
Последнее исправление: olegd (всего исправлений: 1)

Можно ли как-то ускорить сбрасывание?
Реально достаточно писать раз в минуту. Вопрос не в том, как отслеживать память, а как записать этот лог в файл.

man grep, man stdbuf.

В частности:

$ man grep
...
Other Options
    --line-buffered
        Use line buffering on output.
        This can cause a performance penalty.
...

Отчего люди даже не пытаются читать доки?? Ну, ладно, про stdbuf ТС мог и не знать, но почитать доку на grep — для этого не надо иметь семь пядей во лбу. Лежит же на поверхности.

debugger ★★★★★
()
Последнее исправление: debugger (всего исправлений: 3)
Ответ на: комментарий от olegd

как с заданной частотой брать объём памяти и время работы процесса и сохранять в файл так, чтобы информация была видна уже с первой записи?

У меня была та же задача, но мне нужно было мониторить zabbix-ом потребление памяти нужным процессом с интервалом пару раз в секунду. Все что я тестил из консольного – оказалось костыльным и не точным. В итоге, написал прогу на Сишке на десяток строк, которая дергает пару сисколов, парсит вывод и выдает потребление памяти в STDOUT.

iron ★★★★★
()
Последнее исправление: iron (всего исправлений: 1)

Так зачем ты в файл постоянно пишешь?

monitor.sh

#!/bin/bash

# 1. Узнать PID по частичному имени с помощью pgrep
process_name="your_process_name"
pid=$(pgrep -f "$process_name")

if [ -z "$pid" ]; then
  echo "Process not found."
  exit 1
fi

# 2. Проверять, жив ли процесс, и выходить, если он умер
while kill -0 "$pid" 2>/dev/null; do
  # 3. Проверять, сколько процесс потребляет ресурсов
  cpu_usage=$(ps -p "$pid" -o %cpu=)
  mem_usage=$(ps -p "$pid" -o %mem=)
  echo "CPU Usage: $cpu_usage%, Memory Usage: $mem_usage%" >&2

  # Пауза перед следующей проверкой
  sleep 1
done

# 4. Записывать последний результат и время выполнения после выхода из цикла
end_time=$(date +"%Y-%m-%d %H:%M:%S")
echo "Process $pid has terminated at $end_time."
echo "Last CPU Usage: $cpu_usage%, Last Memory Usage: $mem_usage%"
./monitor.sh > result.txt
rtxtxtrx
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)
Ответ на: комментарий от debugger

--line-buffered
stdbuf

Спасибо.

Отчего люди даже не пытаются читать доки??

От того, что линуксовой машины под рукой не было. Был вот этот однострочник, который я когда-то написал в рекламации, а потом добавил в служебную документацию. Была девушка из другого государства, которая вчера пыталась этой документацией пользоваться на более быстрой задаче. И был я, пытающийся одновременно решать свою особо срочную задачу на 3 виндовых машинах, отвечать, почему однострочник не работает, и гадать, за что на прокси заблокировали die.net. Линуксовой машиной я управлял «в режиме марсохода» – писал команды в чат и ждал ответа девушки.

Наверняка, я неоднократно читал про этот ключ. Но в глаза бросалось только «performance penalty», поэтому тут же выбрасывал из головы. Задачи, когда нужно быстродействие между большими паузами, встречаются нечасто.

И кстати о документации. Существует ли ман, перечисляющий назначение всех утилит coreutils?

olegd ★★★
() автор топика
Последнее исправление: olegd (всего исправлений: 1)
Ответ на: комментарий от rtxtxtrx

Так зачем ты в файл постоянно пишешь?

Чтобы получить лог динамики использования памяти программой. Не просто, «сейчас занят гигабайт», а «сейчас занят гигабайт, предыдущие 10 минут было 4 гигабайта, а первые полчаса после старта было 180 мегабайт, значит не все утечки памяти пофиксили».

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

тебе тогда нужно среднее арифметическое считать и максимумы с минимумами. Какой смысл в знании того сколько твоя говнопрога жрала 5 минут назад:

#!/bin/bash

# 1. Узнать PID по частичному имени с помощью pgrep
process_name="your_process_name"
pid=$(pgrep -f "$process_name")

if [ -z "$pid" ]; then
  echo "Process not found."
  exit 1
fi

# Массивы для хранения значений CPU и памяти
cpu_usage_array=()
mem_usage_array=()

# 2. Проверять, жив ли процесс, и выходить, если он умер
while kill -0 "$pid" 2>/dev/null; do
  # 3. Проверять, сколько процесс потребляет ресурсов
  cpu_usage=$(ps -p "$pid" -o %cpu=)
  mem_usage=$(ps -p "$pid" -o %mem=)
  echo "CPU Usage: $cpu_usage%, Memory Usage: $mem_usage%" >&2

  # Добавляем значения в массивы
  cpu_usage_array+=("$cpu_usage")
  mem_usage_array+=("$mem_usage")

  # Пауза перед следующей проверкой
  sleep 0.2
done

# 4. Записывать последний результат и время выполнения после выхода из цикла
end_time=$(date +"%Y-%m-%d %H:%M:%S")
echo "Process $pid has terminated at $end_time."

# Функция для вычисления минимума, среднего и максимума
calculate_stats() {
  local array=("$@")
  local min=${array[0]}
  local max=${array[0]}
  local sum=0
  local count=${#array[@]}

  for value in "${array[@]}"; do
    if (( $(echo "$value < $min" | bc -l) )); then
      min=$value
    fi
    if (( $(echo "$value > $max" | bc -l) )); then
      max=$value
    fi
    sum=$(echo "$sum + $value" | bc -l)
  done

  local avg=$(echo "scale=2; $sum / $count" | bc -l)
  echo "$min $avg $max"
}

# Вычисляем статистику для CPU и памяти
cpu_stats=($(calculate_stats "${cpu_usage_array[@]}"))
mem_stats=($(calculate_stats "${mem_usage_array[@]}"))

# Выводим результаты
echo "CPU Usage: Min: ${cpu_stats[0]}%, Avg: ${cpu_stats[1]}%, Max: ${cpu_stats[2]}%"
echo "Memory Usage: Min: ${mem_stats[0]}%, Avg: ${mem_stats[1]}%, Max: ${mem_stats[2]}%"

Код я не проверял и не буду. Сам перепишешь

rtxtxtrx
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)
Ответ на: комментарий от rtxtxtrx

нужно среднее арифметическое считать и максимумы с минимумами. Какой смысл в знании того сколько твоя говнопрога жрала 5 минут назад:

Для этого и нужен лог. Человек просто открывает его в электронной таблице и считает, что хочет.

На самом деле, там нужна базовая линия.

olegd ★★★
() автор топика
Ответ на: комментарий от iron

В итоге, написал прогу на Сишке на десяток строк

Набось клозедсорсную и неопакеченную под каждый из дистрибутивов…

Shushundr ★★★
()
Ответ на: комментарий от Shushundr

Простые сишные программы можно распространять в виде скриптов для tcc :)

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

От того, что линуксовой машины под рукой не было.
…за что на прокси заблокировали die.net

Ваши злобные прокси так же заблокировали man7.org, www.linuxcommand.org, www.grep.it и www.gnu.org? Достаточно было погуглить man grep.

Наверняка, я неоднократно читал про этот ключ. Но в глаза бросалось только «performance penalty», поэтому тут же выбрасывал из головы.

Ну самому-то не смешно? Ты получаешь инфу обо всех процессах в системе, потом с помощью двух грепов выкидываешь в мусорку всё, кроме одной строки, и при этом тебя заботит «performance penalty»??

Если б тебя действительно заботила производительность этой хрени, ты поступил бы примерно так: почитал man top, нашёл там описание опции -p и воспользовался ею:

$ top -b -d60 -c -p $(pgrep memory_eater) | grep --line-buffered --color=never -F memory_eater > memory.log

Заодно и количество грепов уменьшилось с двух до одного. Можно вообще отказаться от грепа, если подшаманить конфигурацию топа (запустить топ, нажать несколько раз l, t, m, чтобы summary area исчезла, после чего нажать W). Не идеально (т. к. останется пустая строка и строка заголовка таблицы), но сносно. Кроме того, возможно, опять всплывут проблемы с буферизацией вывода (уже на стороне топа), поэтому проще, походу, поискать неинтерактивную тулзу, т. к. топ всё-таки больше заточен под интерактивную работу.

И кстати о документации. Существует ли ман, перечисляющий назначение всех утилит coreutils?

info coreutils либо rpm -ql coreutils | grep -F /bin/.

debugger ★★★★★
()
Ответ на: комментарий от debugger

Ну самому-то не смешно?

Конечно, смешно :)

Ты получаешь инфу обо всех процессах в системе, потом с помощью двух грепов выкидываешь в мусорку всё, кроме одной строки, и при этом тебя заботит «performance penalty»??

Я man grep первый раз читал на AMD K6 без иксов. И с тех пор стал инстинктивно пропускать этот абзац :) Вне связи с текущей задачей.

info coreutils

А на одной странице?

rpm -ql coreutils | grep -F /bin/

А без RH-специфичных программ и с описанием?

olegd ★★★
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.