Разкрихме тайната на Nix пътищата: Защо хешовете не са толкова объркващи
Защо /nix/store има тези странни хешове?
Всеки, който е надникнал в /nix/store, ги е виждал. Онези имена на директории, дето изглеждат сякаш някой е пуснал името на пакет през месомелачка:
/nix/store/s0psayl7zvkvwdcqc8fy1sbv8rlf1yq8-bash-5.3p9
Дясната част е ясна веднага — bash-5.3p9 ти казва точно какво има вътре. Но онези 32 символа преди тирето? Там е цялата работа. И ето какво е важно: повечето обяснения, които ще срещнеш, са непълни.
Стандартното (и грешно) обяснение
„Хешът идва от входните данни" — това е, което повечето хора ще ти кажат. Не грешат точно, но пропускат съществена нюансировка. Истинският въпрос е: кои входни данни? Хешираме ли сорс файловете, които си написал? Рецептата за билд, която Nix генерира? Байтите от самия процес? Зависимостите?
Честният отговор: зависи.
Две схеми за именуване, една директория
Nix използва две различни механизма за именуване на пътища в хранилището, и двата си живеят мирно и кротко под /nix/store. Там започва цялата обърканост.
Input-addressed: имена преди билда
При повечето билдове на пакети, Nix работи като архитект, който преглежда чертежи. Когато напишеш .nix израз, Nix го изчислява в derivation — конкретна спецификация какво да се билдне, включваща:
- Билд скрипта
- Аргументите за компилация
- Променливите на средата
- Декларираните изходи
- Зависимостите
С тази рецепта под ръка, Nix може да изчисли уникален идентификатор още преди билдът да е стартирал. Готовите бинари още ги няма, но Nix вече знае как да ги кръсти.
Ето защо редактирането на .nix израз не винаги променя пътя в хранилището. Ако промените ти не засягат основната рецепта за билд, Nix произвежда същата идентичност. Два различни израза могат да се изчислят до идентични рецепти и да споделят един и същ път. Nix наименува това, което ще билдне — не това как си написал кода.
Content-addressed: имена от байтите
Nix може също така да именува обекти в хранилището директно от съдържанието им. Когато пуснеш nix store add, даваш на Nix нещо, което вече съществува, и то хешира байтите веднага. Няма оценяване, няма рецепта — само съдържание.
Тук пътят се определя от това, което реално е във файла. Промени една буква — хешът е друг.
Защо тази разлика има значение
Разбирането на тези две схеми за именуване прави куп поведения на Nix猛然 ясни:
Предвиждане на промени в пътищата. Ако си се чудиш „редактирането на X ще промени ли пътя в хранилището?", питай се: X променя ли рецептата за билд или действителното съдържание? Промени коментар в .nix израз? Вероятно няма нов път. Промени версия на зависимост? Нов път без дискусия.
Разбирането на съществуващите билдове едновременно. Защо старо билд резултат може да стои до нов в хранилището? Защото имат различни идентичности. Nix не презаписва — просто няма нужда.
Повторното използване на кеш става логично. Един binary cache може спокойно да сервира предварително билднат път, защото името уникално идентифицира входните данни за билда. Същото име значи същото съдържание, гарантирано.
Повече от просто име
Един път в хранилището никога не е наистина сам. Билднатите пакети референсират други пътища в хранилището (динамични библиотеки, интерпретатори, споделени активи), и Nix проследява тези взаимоотношения като граф.
Това не е просто метаданни — това е пълна карта на зависимостите. От всеки път можеш да проследиш неговото затваряне: всичко, което трябва да пътува с него, за да работи на друга машина. Това е начинът, по който nix-copy-closure работи, и защо Nix деплойментите са надеждни.
Същата база данни позволява на Nix да проверява целостта. Може да провери дали байтите на диска все още отговарят на това, което е записано при създаването на пътя. Пътищата в хранилището не са непрозрачни имена на директории — те са запрашими идентичности с пълна одитна следа.
Изводът
Онези криптични хешове не са случайни. Те са резултат от съзнателен дизайнерски избор: Nix именува derivations по входовете им и съдържание по байтите му. Този двоен подход е това, което прави Nix възпроизводим, проверим и учудващо предвидим, след като го разбереш.
Така че следващия път, когато видиш път в хранилището, не се паникьосвай. Чети отдясно наляво — това е човешката част. Хешът отляво е просто начинът на Nix да направи обещание: това име значи този билд, и нищо друго.
Готов да се гмурнеш по-дълбоко? Дали деплойваш контейнери, управляваш инфраструктура, или просто си любопитен за възпроизводимите билдове, разбирането на вътрешната работа на системата винаги си струва. В NameOcean вярваме, че най-добрите разработчици са тези, които наистина разбират какво се случва под капака — не само кои команди да изпълнят.
Успешно билдване.