Files
obsidian-vault/personal/tech/skill-truenas-administration.md
T

4.0 KiB
Executable File
Raw Blame History

title, namespace, type, created, updated, tags, related
title namespace type created updated tags related
skill — truenas-administration personal tech 2026-09-26 2026-09-26
truenas
skill
docker
acl
nfc
personal/plans/tagwriter-container
personal/tech/music-tags-repair-truenas

Зеркало навыка truenas-administration

Навык: ~/.hermes/hermes-whale/skills/devops/truenas-administration/SKILL.md (umbrella: ACL/PUID, ZFS panic recovery, tree comparison, named-volumes→bind-mount).

Ниже — дельта, добавленная 2026-09-26 (сессия music-tags волна 38 + сборка tagwriter).

1. Создание НОВОГО каталога под /mnt/<POOL>/docker/ — из контейнера

/mnt/RED_2TB/docker/ = root:root. truenas_admin (uid 950) не пишет туда; sudo требует пароль (sudo -n → password required). Но docker доступен (юзер в группе docker).

docker run --rm -u 0 -v /mnt/RED_2TB/docker:/docker alpine:latest sh -c \
  'mkdir -p /docker/tagwriter/data && chown -R 950:950 /docker/tagwriter && chmod 755 /docker/tagwriter'

Затем scp проекта обычным путём (владелец 950). Правило: любой новый каталог под docker/ создавать ИЗ КОНТЕЙНЕРА (-u 0), не через ssh под 950.

2. 🔴 Права файлов при scp → COPY в Dockerfile

scp кладёт файлы как -rw------- (600). COPY сохраняет режим → внутри образа /app/<script>.py = root:root 600 → пользователь образа (uid 950) получает python3: can't open file '/app/x.py': [Errno 13] Permission denied, хотя на хосте права 644.

Фикс: в Dockerfile RUN chmod 755 /app/<script>.py && chmod 755 /app + chmod 644 файлов проекта на хосте. Проверка: docker run --rm --entrypoint sh -u 950:950 <img> -c 'id; ls -la /app'.

3. 🔴🔴 NFD на диске vs NFC в данных — путь молча НЕ находится

Батч-задача сверяла манифест (CSV) с реальными файлами → 47 «отсутствующих» файлов, которые лежат на диске. Причина: имена на диске в NFD (разложенная форма: й = и + combining breve U+0306, то же для ё), манифест — в NFC. os.path.exists() → False; ls ничего не показывает; выглядит как «файл удалён».

Поражённые: Али-Баба и сорок разбойников, Принц и нищий (Диск 2), Пеппи Длинный Чулок, Летучий корабль, Голубой щенок — любое имя с й/ё.

# ✅ индекс диска: NFC(путь) -> реальный путь
idx = {}
for root, dirs, files in os.walk(BASE):
    for n in files:
        real = os.path.join(root, n)
        idx[unicodedata.normalize("NFC", real)] = real
real = idx.get(unicodedata.normalize("NFC", wanted))   # None ⇒ действительно нет

Правило: не звать os.path.exists() на не-ASCII путь из манифеста — строить NFC-индекс и искать по нему. Тот же класс, что кейс combining breve для Принц и нищий (Диск 2); применимо к любой батч-задаче с кириллическими путями, не только к музыке. Приёмка: MISSING 47 → 0.

Применение

Оба питфолла воспроизвелись при сборке контейнера personal/plans/tagwriter-container (применение тегов MP3, 7041 файл). Оттуда же — команды docker compose --profile tools run ….