Files
obsidian-vault/family/tech/t610-hang-investigation.md
T

332 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "🔴 t610: зависания — диагностика (незакрыто)"
aliases: [t610 hang, t610 зависание, t610 freeze, RCU stall investigation, MemTotal деградация]
tags: [family, tech, smarthome, t610, incident]
updated: 2026-09-17
---
# 🔴 t610 — зависания: состояние расследования
> **Статус: ПРИЧИНА НЕ УСТАНОВЛЕНА. Главный кандидат — деградация носителя (§5).**
> Сессия 2026-09-17. Ниже — что проверено фактом, что опровергнуто, и что осталось.
> Родительская дока: [[family/how-to/home-automation]] · §3.1 (RCU stall, закрыто), §3.5 (ограничения аддона), §3.9 (память).
>
> ⚡ **Читать в этом порядке:** §1 факты момента смерти → §2 логи недоступны → §4 что опровергнуто
> (**не повторять**) → §5 главный кандидат + как проверить → §7 предложение (ждёт апрува).
---
## 1. Что произошло
Alex перезапустил t610 вручную (сброс питанием) **2026-09-17 ~09:38 +07**.
Хост поднялся заново; HA Core стартовал ~09:4109:43.
**Факты о моменте смерти (из читаемого после ребута):**
| Наблюдение | Значение | Откуда |
|---|---|---|
| Журнал оборван на | `07:2907:31` локально, внезапно, без последней строки | mtime `home-assistant_v2.db` = 07:29, `-wal` = 07:31 |
| БД закрыта чисто? | ❌ **НЕТ**`The system could not validate that the sqlite3 database at //config/home-assistant_v2.db was shutdown cleanly` | `ha core logs` |
| Незакрытая сессия | `Ended unfinished session (id=36 from 2026-09-16 05:46:10)` | тam же |
| Аптайм до ребута | ≈ **26 ч** (сессия с 2026-09-16 05:46 → смерть 07:31) | тam же |
> 🔴 **Ключевой вывод:** процесс **не завершился сам** — БД не закрыта, журнал обрывается
> на полуслове. Система умерла без возможности корректного shutdown (RCU stall / hard freeze),
> а не упала по исключению.
---
## 2. ⛔ Логи прошлого запуска — ДОСТУПА НЕТ (ограничение подтверждено)
Проверено повторно 2026-09-17, подтверждает [[family/how-to/home-automation]] §3.5:
| Источник | Результат |
|---|---|
| `ha core logs` | только **12 строк** текущего контейнера (s6-rc boot) |
| `/config/home-assistant.log.fault` | **0 байт** |
| `/config/home-assistant.log` | **не существует** |
| `journalctl -b -1` | пусто; `/var/log/journal` не существует |
| `ha supervisor logs` | только текущая загрузка (100 строк) |
> 📌 **Следствие, которое надо принять:** после **каждого** жёсткого зависания следы
> стираются. Диагноз надо ставить **до** перезагрузки, либо поднять ретенцию (см. §6).
> Это не «не нашёл» — это структурное свойство HAOS (журнал в RAM).
**Что спасло расследование:** журнал **событий** (логбук) лежит в `/config/home-assistant_v2.db`
и **пережил** ребут. Именно из него реконструирован профиль нагрузки до смерти.
---
## 3. Что проверено ФАКТОМ (данные после ребута)
### 3.1. Хост видит **1.44 ГБ**, не 3.31 ГБ — расхождение с докой
```
MemTotal: 1475788 kB ← 1.44 ГБ ← ЖИВОЙ ФАКТ 2026-09-17
MemFree: 18620 kB ← 18 МБ
MemAvailable: 758304 kB ← 740 МБ
Cached: 837992 kB
SwapTotal: 1024 МБ, used 0
```
> 🔴 **ЭТО ПРОТИВОРЕЧИТ [[family/how-to/home-automation]] §3.9**, где зафиксировано
> `MemTotal: 3 470 792 kB = 3.31 ГиБ` (проверено 2026-09-15).
>
> **Расхождение: 3.31 ГБ → 1.44 ГБ. Это НЕ объясняется округлением.**
#### 3.1.1. ✅ РАЗРЕШЕНО фактом: e820 обрывается на 1.48 ГБ — памяти физически нет выше
Снято 2026-09-17 с живого хоста:
```
BIOS-e820: [mem 0x0000000000000000-0x000000000009ffff] usable
BIOS-e820: [mem 0x0000000000100000-0x000000005e028fff] usable ← верх e820
... ACPI NVS / ACPI data / reserved (много мелких окон) ...
BIOS-e820: [mem 0x000000005e7f4000-0x000000005e7fffff] usable ← ПОСЛЕДНИЙ usable
```
> **Верхняя граница памяти = `0x5e7fffff` ≈ 1.48 ГБ. Выше — ничего.**
>
> **Что это доказывает:** если бы стояла планка 2 ГБ и её часть забирал iGPU/UMA,
> e820 уходил бы за `0x80000000` (2 ГБ). Он обрывается ровно на 1.48 ГБ →
> **сейчас видна одна планка ~1.44 ГБ**, и никакой «вырезанной области» нет.
>
> ⛔ **Версия «iGPU/UMA вырезал ~607 МБ из 2 ГБ» — ОКОНЧАТЕЛЬНО СНЯТА** (см. §4).
> Резерв ACPI NVS/data + reserved ≈ 3040 МБ — это **норма**, не потеря.
>
> 🔑 **Следствие:** в BIOS на старте отдаётся 1.44 ГБ. Если после очередного
> холодного сброса `MemTotal` изменится — это прямое доказательство нестабильности планки/слота.
```bash
# Воспроизведение (только чтение)
ssh root@192.168.2.176 'head -3 /proc/meminfo'
ssh root@192.168.2.176 'dmesg | grep -iE "BIOS-provided|e820.*usable"'
```
> ⚠️ **`dmidecode` на t610 НЕТ** (и `/sys/firmware/dmi/entries/17-*/raw` пуст) —
> число планок этим путём не получить. Смотреть в **BIOS setup** (см. §5.1).
### 3.1.2. 🧩 ЖЕЛЕЗО: HP t610 — 2 слота SO-DIMM, max 4 ГБ (сервис-мануал HP)
Из официального Troubleshooting Guide HP t610 (PDF `c03394393`, изд. 2, июнь 2012):
| Параметр | Значение |
|---|---|
| Слотов | **2 × SO-DIMM**, максимум **4 ГБ** |
| Тип | 204-pin, **DDR3-1600 PC3-12800**, **1.5 В**, non-ECC, CAS 9 |
| ⚠️ Не поддерживается | **x4 SDRAM** (только x8/x16) |
| Порядок заполнения | **SODIMM1, затем SODIMM2** |
| ⚠️ Thermal pad | **Обязателен** на SO-DIMM в **HP t610** (в PLUS-модели — нет) |
| Доступ | **Правая боковая панель** |
| Загрузка с USB | **F10** при старте → boot menu |
> 🔴 HP прямо предупреждает: при апгрейде ставить модули **с золочёными контактами** —
> иначе коррозия/окисление на стыке разных металлов. **Плохой контакт в слоте —
> штатный режим отказа этого железа**, а не экзотика.
>
> ⚠️ **Питание на модули подаётся ВСЕГДА, пока воткнут шнур.** Перед работами —
> отключить кабель и подождать ~30 с (требование HP).
>
> 📌 **Два слота = ступенчатое падение объёма.** Если один слот/планка отваливается,
> `MemTotal` падает ступенькой (2 ГБ → 1 ГБ), и e820 обрезается — ровно то, что видно.
> ⚠️ **НЕ читать `MemFree` как «сколько всего памяти»** (питфоллы 44–45 в родительской доке).
> Alex видел «1 ГБ» на экране — вероятнее всего это `MemFree` в состоянии с большим файловым кэшем,
> **но** живой `MemTotal` 1.44 ГБ — это уже другой разговор, не округление.
### 3.2. Память по контейнерам (норма из доки, для сравнения)
`Node-RED 197 МБ` · `HA Core 212 МБ` · `Supervisor 77 МБ` · `modbus-bridge 20 МБ` ·
`Mosquitto 19 МБ` · `mbusd 0.8 МБ`. Большинство аддонов сейчас **stopped** (nodered, z2m).
### 3.3. Состояние HA после подъёма
| Метрика | Значение |
|---|---|
| Сущностей | 310 |
| Автоматизаций | **23** (22 `on`, 1 `off` намеренно) |
| Выключена намеренно | `automation.ventilation_automation_on` (`last_triggered` 2026-03-12) |
| `unavailable` (Zigbee) | 13 (блок `kitchen_hood`, `office_table_light_switch`, `bedroom/kitchen` light, `shower_2_presence_sensor`, `dushevaia_floor_temperature`) — **ZHA ещё догружается после холодного старта** |
| HA / HAOS | `2026.9.2` / HAOS `18.2` |
| Аддоны | `core_ssh` 10.4.0 (**апдейт до 10.5.0 доступен**), `core_mosquitto`, `local_mbusd`, `local_modbus-bridge`, `local_ustreamer` — started; `nodered`, `zigbee2mqtt` — stopped (как и должно) |
> ✅ **Холодный старт медленный, но штатный:** внешний `https://mallexxx.duckdns.org` начал
> отвечать только через **~1 минуту** после запуска Core. `http://192.168.2.176:8123` из LAN
> даёт `curl` exit 7 (недоступен) — **не поломка**, ходить только через duckdns (питфолл 1).
### 3.4. Профиль нагрузки перед смертью (из логбука, пережил ребут)
Замер на окне `06:3007:40` локально: **1763 записи логбука**.
Доминировали template-сводки:
```
kids_summary / dining_summary / dining_air_summary / bedroom_summary
→ каждые ~5–10 секунд, круглосуточно
```
**Механизм (установлен):**
1. `sensor.kids_co2` / `bedroom_co2` / `dining_co2``platform: mqtt`, приходят от
`modbus-bridge` (сниффер ZONT-шины, `ha.url: http://localhost:8123`, `poll_interval: 15`);
**значение меняется каждый тик** (CO2 живой: 1677 → 1592 ppm за 9 мин).
2. В `/config/configuration.yaml:11721189` объявлены **template-сенсоры БЕЗ `trigger:`**:
```yaml
- name: kids_summary
state: "{{ states('sensor.kids_temperature')|round(0)|int }}° {{ states('sensor.kids_co2')|int }}ppm"
```
Без `trigger` такой сенсор пересчитывается **на любой `state_changed` в системе**, не только
на своих источниках.
3. Замер живьём: `sensor.kids_summary` — **53 изменения за 9 минут** (каждые ~5 с).
4. **`recorder:` блока в `configuration.yaml` НЕТ ВООБЩЕ** → запись всего подряд, дефолт 10 дней,
без `exclude`.
> ⚠️ **Статус версии: ОПРОВЕРГНУТА как причина (Alex, 2026-09-17).**
> «Это обычная работа HA пересчитывать датчики» — верно. Пересчёт шаблонов сам по себе
> **не вешает** систему. Нагрузка на БД реальна (77 МБ БД + WAL 4.4 МБ + поток записи),
> но **связь с зависанием НЕ доказана**. Записано как «контекст нагрузки», а не как причина.
---
## 4. ⛔ Что ОПРОВЕРГНУТО (не повторять)
| Версия | Почему неверна |
|---|---|
| «Template-сенсоры без `trigger` вешают HA» | Alex: это штатная работа HA. Пересчёт — норма, не причина |
| «iGPU/UMA вырезал ~607 МБ из 2 ГБ» | ⛔ **Снято фактом:** e820 обрывается на `0x5e7fffff` (§3.1.1). Выше 1.48 ГБ памяти нет — вырезать нечего |
| «`MemFree` 1 ГБ = кончилась память» | Питфоллы 44–45: `MemFree` падает из-за файлового кэша. Верные метрики — `MemTotal` + `MemAvailable` |
| «Логи есть, надо просто посмотреть внимательнее» | Их **нет** физически (§2). Проверено 5 источников |
| 🔴 «Бэкап-джоб (tar `home-assistant_v2.db`) вешает хост» | Alex: «такая операция по факту ничего не может убить». `tar czf` 77 МБ = секунды чтения + секунды gzip. Докин RCU stall (§3.6 родительской доки) был **непрерывным ffmpeg-ретранскодом**, а не разовой архивацией. **Разница принципиальная** |
| ⚠️ Уточнение по бэкапу | `tar` собирается **НА t610** (`tar czf -` по ssh, stdout → `> OUT` уже на TrueNAS). Значит нагрузка — чтение + gzip **на слабом хосте**. Это уточнение, **не** причина |
> 📌 **Урок метода (для будущих сессий):** я трижды подряд выдал «версию», построенную
> на одной цифре без проверки смежных фактов (template-сенсоры → swap/cache → UMA →
> бэкап-джоб). Каждый раз Alex снимал её одной репликой. **Порядок обратный: сначала
> снять все факты (e820, BIOS, SMART, ретенция метрик), потом формулировать.**
---
## 5. 🎯 ГЛАВНЫЙ КАНДИДАТ: деградация носителя → SQLite disk I/O error
**Найден симптом-матч** (форум HA, тред `1025213`, 15 сентября 2026) — **та же версия стека:**
HA OS `18.2` · Core `2026.9.2` · Supervisor `2026.09`.
**Симптомы у пострадавшего (RPi 5):**
- Фронтенд **недоступен часами** (и локально, и из интернета), при этом **IP пингуется**
- **Несколько перезагрузок не помогали**
- После ребута всё поднималось, через несколько часов — **снова умирало**
- Устройства становились `unavailable`
**Ключевые строки лога:**
```
ERROR (Recorder) [recorder.core] Error in database connectivity during commit:
Error executing query: (sqlite3.OperationalError) disk I/O error
SQLAlchemyError error processing task CommitTask()
sqlalchemy.exc.InvalidRequestError: This session is in 'prepared' state
```
> 🔴 **`sqlite3.OperationalError: disk I/O error` = проблема НОСИТЕЛЯ**, а не софта.
**Как это бьётся с фактами t610:**
| Факт t610 | Объяснение через носитель |
|---|---|
| Обрыв записи БД на `07:29`, shm/wal `07:31` | SQLite упёрся в I/O и перестал писать |
| `could not validate that the sqlite3 database was shutdown cleanly` | БД не закрыта — процесс умер в середине транзакции |
| `Ended unfinished session (id=36)` | Сессия оборвалась на середине |
| Хост не отвечает, сброс только питанием | Классика деградации носителя, **не** OOM и **не** RCU |
| Ошибок в логе нет | Журнал HAOS в RAM — для disk I/O error нужно, чтобы он дожил |
> ⚠️ **Симптом-матч ≠ доказанная причина.** Это **сильнейший из имеющихся кандидатов**,
> потому что объясняет весь набор фактов сразу (§1) и подтверждён на идентичном стеке.
> Проверяется **фактом** — SMART + `dmesg` (§5.2), не рассуждением.
### 5.1. Как проверить память (BIOS + планки)
1. **BIOS setup: `F10` при старте** → `System Information` / `Memory` — **точный объём и число планок**.
Это ответ на «сколько ставит BIOS». Разводит «планка отваливается» от «дока устарела».
2. **`MemTotal` после холодного сброса** — если меняется между загрузками → планка/слот нестабильны (§3.1.1).
3. **Планки по одной** — вынуть вторую, стартовать с первой, затем наоборот.
4. **Контакты** — вынуть, протереть ластиком (HP: золочение обязательно; окисление — штатный отказ).
5. **memtest86+** (`memtest.org`) — грузится с USB, понимает legacy BIOS **и** UEFI.
⚠️ **MemTest86 v11.7 (memtest86.com) — только UEFI**, на t610 **не загрузится**;
для legacy брать **v4**. Гонять **часами**, потом **каждую планку отдельно**.
Показывает и объём **как его видит BIOS**, и ошибки по адресам.
6. 🔑 **Физически «дропнуть 3 ГБ в процессе работы» невозможно** — объём виден ядру
один раз при загрузке через BIOS и не пересчитывается. «Дропнула память» на практике
означает **зависла**, а не потеряла. Режим отказа — **нестабильная планка**: иногда
не определяется с первого раза, иногда ребут, иногда зависон под нагрузкой.
### 5.2. Как проверить носитель (первый приоритет)
```bash
# ① SMART — ГЛАВНЫЙ тест. Ищем НЕНУЛЕВЫЕ:
# Reallocated_Sector_Ct, Current_Pending_Sector,
# Offline_Uncorrectable, UDMA_CRC_Error_Count
ssh root@192.168.2.176 'smartctl -a /dev/sda'
# ② Ошибки I/O в dmesg: ata, I/O error, failed command, medium error, UNC
ssh root@192.168.2.176 'dmesg | grep -iE "ata|I/O error|failed command|medium error|UNC|sense key"'
# ③ Долгий тест (часы)
ssh root@192.168.2.176 'smartctl -t long /dev/sda' # затем -l selftest
# либо badblocks -nsv /dev/sda8
```
> 🔴 **ПИТФОЛЛ 21 родительской доки (§3.4):** свой `find`/`du` по `/mnt/data`
> **сам создаёт I/O-шторм** и даёт **ложный** вывод «диск деградировал».
> **SMART мерить на ЧИСТОМ фоне** — до любых сканирований, либо через ≥60 с.
>
> ⚠️ **`smartctl` в аддоне `core_ssh` может отсутствовать**, а `docker` там нет
> (§3.5 родительской доки). Если не выйдет из аддона — снимать с другого хоста.
---
## 6. ❓ ОТКРЫТЫЕ ВОПРОСЫ
Развилка по времени до зависания (ответ **не получен**):
| Если… | То диагноз | Куда копать |
|---|---|---|
| Вешается через **примерно одинаковый аптайм** | Софт накапливает: утечка, рост БД, исчерпание ресурса | `recorder` + `exclude`, профилирование памяти по контейнерам во времени |
| Вешается **хаотично** | Железо: питание, температура, **HDD 5400 rpm**, **деградация планки RAM** | SMART, `k10temp`, `pressure/io`, `dmesg \| grep -i usb`, BIOS |
Также не выяснено:
- Это **какой по счёту** раз? Есть ли даты/периодичность предыдущих зависаний?
- В момент зависания хост **отвечал вообще** (веб открывался, но тупил) или пропал полностью?
---
## 7. 📋 Предложение (НЕ одобрено, НЕ внедрено)
> ⛔ **Ничего из этого не применено.** План-first: ждёт апрува Alex.
> Правки `configuration.yaml` — только через патч + показ диффа → апрув → заливка → проверка Alex'ом.
1. 🔴 **SMART + `dmesg` по носителю** — **первый приоритет** (§5.2). Сильнейший кандидат §5.
2. **Сбор метрик, переживающий перезагрузку** — раз в минуту писать в файл на `/mnt/data`:
`MemTotal`/`MemAvailable`/`MemFree`, load, `pressure/io`+`pressure/memory`, `k10temp`,
размер БД+WAL, аптайм. **Это то, что даст версию к следующему зависанию** — сейчас каждый
инцидент стирает свои следы (§2).
3. **`recorder:` с `exclude`** — исключить `sensor.*_summary`, `at2_*_summary`, `update.*`,
`button.*_identify`, `event.*`. Снижает нагрузку на БД. **Не «фикс зависания»** — отдельное улучшение.
4. **Включить watchdog `local_ustreamer`** — единственный аддон без watchdog (§3.7 родительской доки).
5. **Обновить `core_ssh`** 10.4.0 → 10.5.0.
> 📌 Версия **«что именно вешает»** появится **только после п.1+п.2**. Без ретенции расследование
> упирается в §2 и превращается в перебор гипотез — что и произошло в сессии 2026-09-17.
---
## 8. Питфоллы сессии (дополнение к родительской доке)
| # | Питфолл | Обход |
|---|---|---|
| 53 | 🔴 **Журнал прошлого запуска недоступен ПОСЛЕ жёсткого зависания** — подтверждено повторно, 5 источников пусты | Ставить диагноз ДО ребута, либо ретенция (§7.2). Логбук в `home-assistant_v2.db` **переживает** ребут — использовать его |
| 54 | ⚠️ **`ha core logs` показывает только текущий контейнер** (12 строк s6-rc), не историю | Не искать «старые строки» — их нет |
| 55 | ⚠️ **`MemTotal` может расходиться с докой** — живой факт `1.44 ГБ` против зафиксированных `3.31 ГБ` (§3.9 родительской доки) | Всегда перемерять `head -3 /proc/meminfo` + e820 при разборе инцидента, не полагаться на записанное |
| 56 | 🔴 **`http://192.168.2.176:8123` из LAN → `curl` exit 7, хоть хост жив** | Единственный путь к API — `https://mallexxx.duckdns.org`. Совпадает с питфоллом 1 |
| 57 | ⚠️ **После холодного старта ZHA догружается**: часть сущностей минуты висит `unavailable` | Не спешить с выводом «устройства отвалились» — перемерить через 2–3 мин. Первый снимок дал 75 сущностей, полный — 310 |
| 58 | 🔴 **`dmidecode` на t610 НЕТ**, `/sys/firmware/dmi/entries/17-*/raw` пуст | Число/объём планок — только **BIOS setup** (F10). `MemTotal` + e820 дают объём, но не число планок |
| 59 | 🔴 **`dmesg` на t610 требует `\| tail`** — без хвоста врёт (питфолл 5 родительской доки, подтверждён) | Всегда `dmesg \| grep … \| tail` |
| 60 | 🔴 **Порядок расследования: ФАКТЫ → версия, а не версия → проверка** | Три подряд опровергнутые «версии» (§4) съели сессию. Сначала e820/BIOS/SMART/метрики, потом формулировка |
| 61 | ⚠️ **Симптом-матч с форума ≠ доказательство** | Тред `1025213` совпал по версии стека и симптомам, но это **кандидат**, не причина. Закрывать только фактом по §5.2 |