4.0 KiB
Executable File
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-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 ….