Wb-rules поджирает память. Чем можно помониторить?

Добрый день.

Можно ли как-то более детально посмотреть за потреблением памяти wb-rules, особенно с детализацией по потокам/скриптам?

Что-то 2-3 раза в сутки выжирает память и не до конца возвращает обратно - то ли скрипт глючит, то ли ещё что. На картинке график свободной памяти, пик центре - после рестарта wb-rules. Доходило до того, что oom-killer убивал node-red и ещё что-то. Возможно, что как-то связано с использованием таймеров в скриптах (отключил

приложен диагностический архив, доступен только сотрудникам поддержки
(442,2 КБ)

скрипт для показа/установки системного времени - тут в примерах было - стало чуть лучше, но не радикально)

WB 8.5.3A/4G1 1.3.4B-4G2, S/N: ACHKS33M, wb-2507-stable

Добрый день.

Нет, для wb-rules нет более детальных логов.

Да, если явно не чистить отработавший экземпляр - возможно.

Оптимальный способ диагностики, пожалуй - убрать (отключить) правила и включать по одному.
Пробовали?

Хм. Мысль©.

Там используется startTicker для регулировки яркости ламп. Его как-то можно/нужно освобождать? Сходу не помню, надо мануалы поизучать. Вроде от не возвращает handle как setTimeout. Так-то, вроде, этим никто не пользуется, но вариант ложного срабатывания и пуска не исключаю.

Отключать всё - не вариант - там освещение офиса и юзвери будут недовольны :slight_smile:

Периодический не надо освобождать, если не создаются дополнительные экземпляры.

Там, вроде, запуск по длинному нажатию (плавное изменение яркости) и, подозреваю, нет никакого освобождения - надо проверить, какой код реально в железе. В ночь или завтра посмотрю и оставлю на проверку на полдня-день

Утра.

Сделал вчера вечером “apt-get upgrade”, оказалось - зря, ибо обновилось до wb-2602. Но хуже то, что жор памяти явно увеличился - с 55Мб при запуске до 310Мб через 12 часов. Ругани в логах от wb-rules - нет.

Есть ли какая-то статистика, какое “среднее” потребление памяти у wb-rules?

Отключил все скрипты, кроме освещения - ещё полдня понаблюдаю…

Сейчас аптайм небольшой:

uptime
 11:41:19 up 8 days,  7:32,  1 user,  load average: 1.41, 1.80, 2.02

Смотрю на память:

systemctl show wb-rules -p MainPID -p MemoryCurrent -p MemoryPeak -p TasksCurrent; pid=$(systemctl show -p MainPID --value wb-rules); echo "---"; if [ -n "$pid" ] && [ "$pid" -gt 0 ] 2>/dev/null; then ps -p "$pid" -o pid,comm,rss,vsz,%mem --no-headers; else echo "wb-rules MainPID not found"; fi 
MainPID=1914
MemoryCurrent=71786496
TasksCurrent=31
---
 1914 wb-rules        62840 948048  6.1

То есть да, прилично, около 70МБ. Но и скриптов там с десяток.
Потребление не увеличивается.

О! Вопрос: а число потоков wb-rules как-то зависит от кол-ва скриптов? И таки хочется видеть, какой из потоков для чего запущен (хз, мож можно какой признак выставить, чтоб в top/htop его увидеть).

У меня число потоков, вроде, не зависит от числа работающих скриптов. Так-то там 5-7 скриптов, из них 2 “техническиких”, типа мониторниг перезапуска mqtt-serial и живости eMMC, один с запуском shell nodejs и только два оставшихся настораживают - там под 100 “простых” виртуальных устройств типа “CW-WW лампа” с реакцией только на события, и ≈20 “групп ламп+выключатель”, где используется таймер.

Состояние на сейчас:

  • восстановил простой скрипт с регулярным пуском (через shell) nodejs скрипта - вроде не влияет
  • пока остановлены “технические” и 2 “простых” скрипта для сбора регистров modbus в JSON от Овен и С200ПП, но вряд ли они - там почти тривиальная трансляция без изысков
  • в подозрительном скрипте на освещние отключил блок с startTicker/timers[xxx].stop()
  • память пока не утекает, но надо ждать от 12 до 20 часов, судя по логам

Основное предположение и вопрос (пока) - а что происходит с памятью, если я вызываю “timers[name+’test’].stop()” для таймера, который не запускал?

Пока основной, но не очевидной причиной видится именно эта строка. Типа “стоп таймера изменения яркости при ЛЮБОМ изменении состояния кнопок” (пуск - по длинному нажатию, стоп - по нажатию/отпусканию/итп любой из пары кнопок)

С утра (стоп 2х простых скриптов и блокировка использования таймера) память ±5Мб не меняется - 220±3Мб, да не 48, как на другом контроллере, но не “течёт”. Ну и частичное обновление на 2602, возможно как-то повлияло.

Давайте, я до (примерно) завтра посмотрю за потреблением памяти, ибо “провал” происходил раз в 8-12-18 часов.

А для программистов вопрос - насколько “безболезненно” вызывать timers[xxx].stop(), если startTicker(xxx) НЕ вызывался

=== для информации

systemctl show wb-rules -p MainPID -p MemoryCurrent -p MemoryPeak -p TasksCurrent; pid=$(systemctl show -p MainPID --value wb-rules); echo "---"; if [ -n "$pid" ] && [ "$pid" -gt 0 ] 2>/dev/null; then ps -p "$pid" -o pid,comm,rss,vsz,%mem --no-headers; else echo "wb-rules MainPID not found"; fi 
MainPID=960249
MemoryCurrent=213622784
TasksCurrent=20
---
 960249 wb-rules        227448 2927020  5.6

Я не исследовал, но по-моему нет.
Спрошу у разработчиков.

Надо исследовать. Сходу не скажу. Вопросы хорошие.
То есть запланирую себе на следующую неделю.

Предварительно скажу, что чтобы да - так - нет ©

Примерно под 250-200Мб поджирается за ночь.

После отключения события с таймером - стало получше, нет провалов на 1Гб, но не уверен, что это причина.

Всё равно, судя по графику, раз 2-4-6-8-… часов что-то происходит, сжирает память, и она остаётся у wb-rules.

Ща, на выходные отключу скрипты освещения, надеюсь, побьют за это не очень сильно. Чтобы совсем исключить влияние логики. Начиная с понедельника - посмотрим-обсудим.

Т.е. Сильно лучше, но таки что-то происходит раз в 2-3-4.5-и т.д. часов, что не отдаёт память обратно

Я такой у себя запустил:

log.info("ramLog: запуск");

function makeNewVirtualControl(vdName, nameControl, typeControl) {
  log.info("Define new");
  defineVirtualDevice(vdName, {
    title: vdName,
    cells: {}
  });

  var vdev = getDevice(vdName);

  // Проверим, есть ли контрол; если нет, создадим его.
  if (!vdev.isControlExists(nameControl)) {
    log.debug("Контрола {} нет, создаем.", nameControl);
    vdev.addControl(nameControl, typeControl);
  }
}

var RAM_VDEV_NAME = "ramLog";
var RAM_CONTROL_NAME = "occupedRAM";

makeNewVirtualControl(RAM_VDEV_NAME, RAM_CONTROL_NAME, {
  type: "value",
  value: 0,
  units: "kB",
  readonly: true,
  forceDefault: false
});

function updateWbRulesRamUsage() {
  // Суммируем RSS (kB) для всех процессов wb-rules.
  runShellCommand("ps -C wb-rules -o rss= | awk '{sum+=$1} END {print (sum ? sum : 0)}'", {
    captureOutput: true,
    exitCallback: function (exitCode, capturedOutput) {
      if (exitCode !== 0) {
        log.warning("ramLog: команда завершилась с кодом {}", exitCode);
        return;
      }

      var value = parseInt(String(capturedOutput).trim(), 10);
      if (isNaN(value)) {
        log.warning("ramLog: не удалось разобрать значение RAM из '{}'", capturedOutput);
        return;
      }

      dev[RAM_VDEV_NAME + "/" + RAM_CONTROL_NAME] = value;
      log.debug("ramLog: wb-rules RSS = {} kB", value);
    }
  });
}

// Первичное обновление при старте скрипта.
updateWbRulesRamUsage();

// Обновление каждую минуту.
setInterval(function () {
  updateWbRulesRamUsage();
}, 60 * 1000);

Получаю около 25МБ RSS, не меняется.

А нету ли вызова “чего-то” по cron?

По системному Крон-у ничего нет, но потенциально есть пара скриптов с when по cron. Сейчас работает только один из них - шлёт раз в минуту потребление wb-rules в MQTT (примерно аналогично приведённому выше)

На данный момент под подозрение попал cloud-telegraph с вариантом, когда он не может отправить метрики. Остановил сегодня утром, до завтра понаблюдаю (пока провалов нет, но и 12 часов не прошло).

На данный момент ±5Мб стабильно, но wb-rules RSS 500Мб и не освобождается. При рестарте сервиса где-то 150Мб

Ого… Подобное у меня получилось при создании разом около 2000 правил.

Вот и мне непонятно. Вроде ничего особенного нет - 100 виртуальных устройств, НЕ связанных с железом, но использующих mqttPublish плюс ≈30 устройств связанных с кнопками (counter одинорное-двойное-длинное).

К ночи попробую остановить всё и перезапустить wb-rules с полностью отключенными скриптами

UPD: Пока за ночь, когда никого нет и светом не балуются, RSS растёт примерно на 200Мб. В логах (было) сообщения об отправки метрик и периодические ошибки на 485 (типа из errata). Посмотрим, что будет без telegraph

Приветствую!

Ниthего не понимаю! © Колобки

Таки память, похоже, жрётся при запущенных скриптах. Причём даже тогда, когда ничего не происходит - ночь, освещение никто не трогает. Скрипты раз в минуту отправляют JSON с состоянием ламп.

Второй момент - не очевидно поведение. То практически не растёт потребление, то “ступеньками”. При рестарте wb-rules виртуальные устройства создаются секунд 30. Очередное предположение - race condition где-то, возможно при создании. Первый скрипт создаёт “лампы”, второй “комнаты” и использует созданные выше “лампы”.

Вот картинка за 2.5 суток

До кучи - диагностический архив и используемые скрипты:

приложен диагностический архив, доступен только сотрудникам поддержки
(397,6 КБ)

rules.tar.gz (7,2 КБ)

ЗЫ: а откуда берутся данные в wb-rules-metrics.log ? Можно их как-то вживую помониторить?

Попробую воспроизвести.
Ну и советую включить debug для wb-rules. Поскольку полки в графике видны - скорее всего получится соотнести с записями.

Конечно можно. Из сам сервис и отдает: wb-diag-collect/wb-diag-collect.conf at 80b5f0e2645e689a33e79b4ee687a3d5998259f5 · wirenboard/wb-diag-collect · GitHub

Попробую посохранять метрики для сравнения, вдруг что-то прояснится

Debug включал часов на 12-15 - в районе полок пусто. Только отметки от лога занимаемой памяти “внезапно” меняются на несколько Мб, потом “отскакивают”, но не до конца.

Единственное, что как-то совпадает в системном логе - примерно в это время вываливается несколько ошибок в modbus-485 (предполагаю из ERRWB84009)

Вот свежий кусок из лога (потребление памяти не изменилось. Строка с 'parse fail’ - штатное поведение)

2026-04-01 12:10:42 WbRules usage: 451576
2026-04-01 12:11:42 WbRules usage: 451576
2026-04-01 12:12:28 ON BUTTON R109 => M05/Input 2 Single Press Counter == 28
2026-04-01 12:12:28 Rule R109_virt(toggle, R109,cmd)
2026-04-01 12:12:28 #R109 newValue parse fail: SyntaxError: invalid json
2026-04-01 12:12:28 Rule R109_virt(true, R109,state)
2026-04-01 12:12:28 Rule R109_virt( , R109,cmd)
2026-04-01 12:12:28 LAMP L109_1/state => 'true', type: boolean
2026-04-01 12:12:28 L109_1: MQTT ON
2026-04-01 12:12:28 LAMP L109_2/state => 'true', type: boolean
2026-04-01 12:12:28 L109_2: MQTT ON
2026-04-01 12:12:28 LAMP L109_3/state => 'true', type: boolean
2026-04-01 12:12:28 L109_3: MQTT ON
2026-04-01 12:12:42 WbRules usage: 451576
2026-04-01 12:13:42 WbRules usage: 451576

Debug - не пишется в журналы, он публикуется в топик /wbrules/log/debug
То есть то что выводится в консоль отладки - для debug сообщений по факту читается из топика

Да, уже увидел в топике про node-red.

Собс-но оставлял консоль отладки открытой. Сейчас подключился через mosquitto_sub и пишу в файл.

Предварительно - сработка скриптов не влияет на разницу потребления. Сделал bash скрипт в контроллере, что пишет метрики в файл при изменении потребления. С Go почти не знаком, посему чего-то критичного не увидел, кроме изменений потребления (какой-то) памяти.

Вот такие цифры поучаются (дата-время, насколько изменилось, сколько в итоге):

root@wirenboard-ACHKS33M:~/test-log# ./get_logs 
Start RAM: 445768
20260401-131440 Changed 6140 => 451908
20260401-131841 Changed 128 => 452036
20260401-133641 Changed 97576 => 549612
20260401-133741 Changed 31892 => 581504
20260401-133842 Changed -42572 => 538932
20260401-133942 Changed -22280 => 516652
20260401-134342 Changed 1152 => 517804
20260401-134442 Changed 172 => 517976
20260401-134542 Changed 1408 => 519384
20260401-134642 Changed 6288 => 525672
20260401-134842 Changed 4312 => 529984
20260401-135042 Changed 8664 => 538648
20260401-135242 Changed 6444 => 545092
20260401-135442 Changed 2044 => 547136
20260401-140043 Changed 2180 => 549316
20260401-140143 Changed 128 => 549444
20260401-140343 Changed 128 => 549572
20260401-140743 Changed 128 => 549700
20260401-142344 Changed 128 => 549828
20260401-152546 Changed -140 => 549688
20260401-153746 Changed 128 => 549816

Размышление на тему…

Если это race-condition при рестарте/disable-enable скрипта, то вопрос:

Как (условно) асинхронно создать 100 виртуальных устройств и/или как дождаться создания всех виртуальных устройств из одного файла скрипта в другом?

…на данный момент длится “полка” с 18:03, очередной всплеск ожидаю после 23:00. Как и раньше - сработки скриптов не коррелируют с изменением потребления памяти.