Pull to refresh

3. Nix в пилюлях: Погружаемся в среду

Level of difficultyMedium
Reading time6 min
Views1.9K
Original author: Luca Bruno

Добро пожаловать на третью Nix-пилюлю. Во второй пилюле мы установили Nix на свою систему.
Сейчас мы, наконец, можем с ним поэкспериментировать.
Статья будет полезной, даже если вы пользуетесь не просто Nix, а NixOS.

Начинаем погружение

Если вы используете NixOS, вы можете пропустить следующий раздел — Устанавливаем что-нибудь.

В предыдущей статье мы создали пользователя Nix. Давайте переключимся на него с помощью команды su - nix.
Если ваш ~/.profile уже создан, вам должны быть доступны команды наподобие nix-env и nix-store.

Если нет, запустите:

$ source ~/.nix-profile/etc/profile.d/nix.sh

В прошлой статье мы выяснили, что ~/.nix-profile/etc указывает на порождение nix-2.1.3.
В данный момент мы находимся в профиле пользователя Nix.

(Адрес этой статьи на официальном сайте перевода).

Устанавливаем что-нибудь

И вот она, практика!
Установка в окружение Nix — интересный процесс.
Начнём с hello — простой командной утилиты, которая печатает Hello world и часто используется для проверки компиляторов и пакетных менеджеров.

Итак, установка:

$ nix-env -i hello
installing 'hello-2.10'
[...]
building '/nix/store/0vqw0ssmh6y5zj48yg34gc6macr883xk-user-environment.drv'...
created 36 symlinks in user environment

Теперь программу можно запускать.
Прежде, чем двигаться дальше, зафиксируем несколько важных моментов:

  • Мы установили программу с правами пользователя Nix, и только для пользователя Nix.

  • Из-за этого появилось новое окружение пользователя (иногда его называют средой пользователя). Это — новое поколение профиля нашего пользователя Nix.

  • Утилита nix-env управляет окружениями, профилями и их поколенями.

  • Мы установили hello, используя только имя, без указания версии. Повторяю: мы указали только имя деривации (без версии) для установки.

Мы можем вывести список поколений без блужданий по каталогу /nix:

$ nix-env --list-generations
   1   2014-07-24 09:23:30
   2   2014-07-25 08:45:01   (current)

Вывести установленные деривации:

$ nix-env -q
nix-2.1.3
hello-2.10

Куда мы установили hello на самом деле? which hello даёт нам ~/.nix-profile/bin/hello, который указывает на хранилище.
Мы также можем вывести путь деривации с помощью команды nix-env -q --out-path.
Этот путь деривации называется выходом сборки.

Слияние путей

Сейчас вы, возможно, хотите запустить man чтобы получить кое-какую информацию.
Даже если у вас уже есть man в основной системе, вы можете установить её в окружение Nix с помощью команды nix-env -i man-db.

Исследуем профиль:

$ ls -l ~/.nix-profile/
dr-xr-xr-x 2 nix nix 4096 Jan  1  1970 bin
lrwxrwxrwx 1 nix nix   55 Jan  1  1970 etc -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/etc
[...]

Мы видим кое-что интересное.
Когда у нас была установлена только одна деривация nix-2.1.3, bin был символической ссылкой на nix-2.1.3.
Теперь, когда мы дополнительно установили несколько программ (man, hello), bin стал реальным каталогом, не симлинком.

$ ls -l ~/.nix-profile/bin/
[...]
man -> /nix/store/83cn9ing5sc6644h50dqzzfxcs07r2jn-man-1.6g/bin/man
[...]
nix-env -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env
[...]
hello -> /nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10/bin/hello
[...]

Так, кое-что стало проясняться. nix-env слил пути из установленных дериваций.
which man указывает на профиль Nix, вместо того, чтобы указывать на системный man, потому что ~/.nix-profile/bin находится в начале $PATH (путь к системному man находится в списке путей позже и программа which его не видит — примечание переводчика).

Откат и переключение поколений

Последняя установленная команда — это man.
Сейчас мы находимся в поколении профиля номер 3, если вы ничего не меняли на предыдущих шагах.
Мы можем откатиться к предыдущему поколению:

$ nix-env --rollback
switching from generation 3 to 2

Теперь nix-env -q не показывет man.
Команда ls -l \which man`` должна вывести содержимое каталога основной системы.

Разобравшись с откатом, вернёмся обратно в поколение 3:

$ nix-env -G 3
switching from generation 2 to 3

Самое время познакомиться со справкой на команду nix-env.
Для запуска nix-env нужно указывать операцию.
Можно добавлять опции.
Часть опций общие, а часть — специфичные для отдельных операций.

Конечно, вы можете и удалять и обновлять пакеты.

Запросы в хранилище

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

Для этого у нас есть команда nix-store.
Она предоставляет широкие возможности, но пока мы познакомимся только с несколькими видами запросов.

Чтобы вывести непосредственные зависимости программы hello:

$ nix-store -q --references `which hello`
/nix/store/fg4yq8i8wd08xg3fy58l6q73cjy8hjr2-glibc-2.27
/nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10

Аргумент nix-store может иметь любой тип, если он находится в хранилище Nix.
Утилита следует симлинкам.

Сейчас это может показаться неважным, но давайте просмотрим деривации, зависящие от hello:

$ nix-store -q --referrers `which hello`
/nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10
/nix/store/fhvy2550cpmjgcjcx5rzz328i0kfv3z3-env-manifest.nix
/nix/store/yzdk0xvr0b8dcwhi2nns6d75k2ha5208-env-manifest.nix
/nix/store/mp987abm20c70pl8p31ljw1r5by4xwfw-user-environment
/nix/store/ppr3qbq7fk2m2pa49i2z3i32cvfhsv7p-user-environment

Призайтесь, вы этого не ждали?
Оказывается, наши окружения зависят от hello.
Да, это значит, что окружения также находятся в хранилище, и поскольку они содержат симлинки на hello, каждое окружение зависит от hello.

Мы видим в списке два окружения, относящиеся к поколениям 2 и 3, так как именно они содержат установленную программу hello.

Файл manifest.nix содержит метаданные, относящиеся к окружению, например, список установленных дериваций.
Команда nix-env может выводить, обновлять и удалять их.
И снова — текущий manifest.nix находится по пути ~/.nix-profile/manifest.nix.

Замыкания

Замыкание деривации — это рекурсивный список всех её зависимостей, который включает абсолютно всё, что нужно для использования данной деривации.

$ nix-store -qR `which man`
[...]

Копирование всех этих дериваций в хранилище на другой машине, позволит запустить на ней утилиту man, ничего больше не настраивая.
Это — основа развёртывания с помощю Nix. Думаю, вы уже догадываетесь, насколько это мощный и удобный инструмент для работы с облаками.

Просмотр замыкания в виде дерева зависимостей:

$ nix-store -q --tree `which man`
[...]

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

То же самое относится и к окружениям.
В качестве упражнения запустите nix-store -q --tree ~/.nix-profile и убедитесь, что прямыми наследниками окружения пользователя являются установленные деривации и файл manifest.nix.

Разрешение зависимостей

В Nix нет ничего похожего на apt которая решает задачу выполнимости булевых формул (SAT problem), чтобы подобрать зависимости с учётом верхних и нижних границ версий.
Вся эта сложность не нужна, потому что все зависимости статичны: если деривация X зависит от деривации Y, она зависит от неё всегда.
Деривация X, которая зависит от Z, должна быть другой деривацией.

Ручное восстановление

$ nix-env -e '*'
uninstalling 'hello-2.10'
uninstalling 'nix-2.1.3'
[...]

Ой, команда удалила все деривации из окружения, включая сам Nix!
Это значит, что теперь мы не можем запустить даже nix-env.
Что делать?

Раньше мы получали доступ к nix-env из окружения.
Окружения удобны для пользователей, но Nix всё ещё находится в хранилище!

Сначала выберем одну из дериваций nix-2.1.3: ls /nix/store/*nix-2.1.3, пусть это будет /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3.

Первый способ всё починить — откатить изменения:

$ /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env --rollback

Второй способ — заново установить nix-env, тем самым создав новое поколение:

$ /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env -i /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env

Каналы

Откуда берутся пакеты?
Мы уже говорили об этом во второй статье.
Есть список каналов, откуда мы получаем пакеты, хотя обычно мы используем только один.
И есть утилита для управления каналами — nix-channel.

$ nix-channel --list
nixpkgs http://nixos.org/channels/nixpkgs-unstable

Если вы используете NixOS, вы можете не увидеть вывода этой команды (если используете настройки по умолчанию), либо вы можете увидеть канал, чьё имя начинается с "nixos-" вместо "nixpkgs".

По сути, это содержимое файла ~/.nix-channels.

ℹ️ ~/.nix-channels — это не символическая ссылка на хранилище!

Для обновления канала запустите nix-channel --update.
Эта команда скачает новые выражения Nix (описания пакетов), создаст новое поколнение профиля каналов и распакует его в ~/.nix-defexpr/channels.

Она немного похожа на apt-get update.
(См. таблицу, где в первом приближении сравниваются средства управления пакетами Ubuntu и NixOS).

Заключение

Мы узнали, как исследовать окружение пользователя и изменять его, устанавливая и удаляя программы.
Обновлять программы тоже не сложно, подробности см. в руководстве (вкратце: nix-env -u обновит все пакеты в окружении).

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

Далее, мы выяснили, как исследовать хранилище.
Мы изучили зависимости и обратные зависимости путей в хранилище.

Мы увидели, как симлинки используются для слияния путей из хранилища Nix — полезный трюк.

Подходящая аналогия с языками программирования: у вас есть куча с объектами, и она похожа на хранилище Nix.
У вас есть объекты, которые указывают на другие объекты, они похожи на деривации.
Возможно, эта метафора поможет вам понять, как деривации ссылаются друг на друга.

В следующей пилюле

...мы изучим основы языка Nix.
Язык Nix используется, чтобы описывать, как строить деривации.
Он является основой всего, включая NixOS.
Поэтому очень важно понимать как синтаксис, так и семантику языка.

Tags:
Hubs:
Total votes 4: ↑4 and ↓0+6
Comments0

Articles