`libalternatives` в openSUSE: майбутнє управління альтернативами
Управління декількома версіями одного інструмента - правильний шлях для сучасних дистрибутивів.
Table of Contents
- Вступ: навіщо потрібен механізм альтернатив
- Чому
update-alternativesвже не задовольняє сучасні потреби - Що таке
libalternatives - Порівняння:
update-alternativesvslibalternatives - Команди
alts: довідник - Висновки
- Швидка шпаргалка
Вступ: навіщо потрібен механізм альтернатив
update-alternatives - це класичний Linux-інструмент для управління симлінками команд, що мають декілька встановлених реалізацій. Кожен пакет реєструє себе як альтернативу для певної ролі (editor, java, python тощо), а система зберігає симлінки в /etc/alternatives/, вказуючи на поточну альтернативу з найвищим пріоритетом.
Спочатку це була Debian-тулза, але її швидко підхопили всі популярні дистрибутиви. Проте, з розвитком сучасних файлових систем і архітектур дистрибутивів, classic approach почав виявляти свої обмеження.
Чому update-alternatives вже не задовольняє сучасні потреби
Насправді, для більшості дистрибутивів він працює добре. Всіх, крім одного. openSUSE, з його унікальною архітектурою на базі Btrfs та snapshots, зіткнувся з фундаментальною проблемою.
Проблема 1: лише одна активна альтернатива
Симлінк може вказувати тільки на одну ціль. Для простих випадків (наприклад, вибір між vim і nano) цього достатньо. Однак коли мова йде про розробку, де одночасно встановлені Node.js 18, 20 і 22, виникають проблеми.
Сценарій:
- Ви явно запускаєте програму через
node18 - Вона викликає дочірній процес через
#!/usr/bin/node - Дочірній процес запускається на Node.js 22 (бо симлінк
/usr/bin/nodeвказує на неї) - Результат: непередбачувана поведінка і важкі для діагностики помилки
Проблема 2: відсутність юзер-левел налаштувань
update-alternatives - це інструмент системного адміністратора. Звичайний користувач без прав root не може змінити налаштування для свого облікового запису. Єдиний обхідний шлях - ручні симлінки у ~/.local/bin, що не є універсальним рішенням.
Проблема 3: /var і снапшоти (головна проблема для openSUSE)
Ось де openSUSE зіткнувся з архітектурним обмеженням:
update-alternativesзберігає свій стан у/var/lib/alternatives/- У openSUSE коренева файлова система (
/) снапшотується через Btrfs /varнавмисно винесений в окремий btrfs-subvolume, який не входить до снапшоту
Наслідки: Коли ви встановлюєте пакет, RPM-скрипти викликають update-alternatives, який записує стан у /var/lib/alternatives/. Цей запис існує поза снапшотом. Якщо ви виконуєте rollback системи до попереднього снапшоту - /var залишається з новим станом, а стан пакетів у снапшоті розходиться зі станом alternatives. Система стає неконсистентною.
Для звичайного Tumbleweed-робочого столу це може бути неприємністю. Для MicroOS або будь-якої image-based системи - це концептуальна несумісність. Коли ОС побудована навколо атомарних оновлень і гарантованих rollback’ів, механізм, що зберігає стан за межами снапшотів, є архітектурним протиріччям.
Що таке libalternatives
libalternatives - це інноваційний підхід, запропонований Adam Majer у 2021 році в розсилці openSUSE Factory. Основна ідея: перенести логіку вибору версії з «магічного симлінка» в бібліотеку часу виконання.
Архітектура
| Компонент | update-alternatives | libalternatives |
|---|---|---|
| Тип | Інструмент часу встановлення | Бібліотека часу виконання |
| Модифікація стану | Так (під час встановлення пакета) | Ні (тільки читання під час виконання) |
| Збереження конфігурації | /var/lib/alternatives/ | /usr/share/libalternatives/ |
Технічна реалізація
Конфігураційні файли: Пакет розміщує в
/usr/share/libalternatives/<ім'я_програми>/<пріоритет>.confфайл з описом альтернативи. Наприклад:/usr/share/libalternatives/java/3000.confз вмістом:
binary=/usr/lib64/jvm/graalvm-jdk-25.0.1+8.1/bin/java group=java,keytool,rmiregistryБінарники: Самі бінарники (
/usr/bin/java,/usr/bin/nodeтощо) стають симлінками на/usr/bin/altsМеханізм роботи: Коли ви запускаєте
java, насправді виконуєтьсяalts, який:- Через
argv[0]розуміє, яку програму викликали - Читає конфігураційні файли з
/usr/share/libalternatives/java/ - Враховує системні та користувацькі уподобання (за пріоритетами)
- Передає виклик потрібному бінарнику через
exec()
- Через
Переваги архітектури
- Конфігурація у складі пакета: Файли в
/usr/share/є частиною пакета і входять до знімку файлової системи - Атомарність: Rollback повертає все в узгоджений стан, включно зі станом альтернатив
- Ніяких записів у
/var/: Уникнення проблеми з снапшотами
Ієрархія пріоритетів
libalternatives використовує прозору ієрархію:
юзер → адміністратор → пакет Юзерські налаштування (у ~/.config/libalternatives/) мають найвищий пріоритет. Системний адміністратор може встановити одне значення, пакет - запропонувати інше, але вибір користувача переважить обидва.
Важливо: Користувач вибирає пріоритет (числове значення), а не шлях до бінарника. Пріоритети визначаються пакетами у їхніх конфігураційних файлах.
Порівняння: update-alternatives vs libalternatives
| Аспект | update-alternatives | libalternatives |
|---|---|---|
| Тип | Інструмент часу встановлення | Бібліотека часу виконання |
| Збереження стану | /var/lib/alternatives/ | /usr/share/libalternatives/ |
| Сумісність зі снапшотами | Ні (стан поза снапшотом) | Так (стан у складі снапшота) |
| Юзер-левел налаштування | Ні (потрібен root) | Так (~/.config/libalternatives/) |
| Overhead при запуску | Ні (прямий симлінк) | Так (читання конфігурації + exec()) |
| Сумісність з іншими дистрибутивами | Так (стандарт de-facto) | Ні (тільки openSUSE) |
| Управління slave links | Так (через --slave) | Так (через конфігураційні файли, параметр group) |
| Рівень control | Системний | Системний + користувацький |
Команди alts: довідник
Управління libalternatives здійснюється через команду alts. На відміну від update-alternatives, де вказується шлях до бінарника, у libalternatives вибирається пріоритет альтернативи.
| Команда | Опис | Приклад |
|---|---|---|
alts -l | Показує всі зареєстровані програми | alts -l |
alts -l <name> | Показує всі доступні альтернативи для вказаної програми | alts -l java |
alts -t <name> | Показує поточну цільову альтернативу для програми | alts -t java |
alts -u -n <name> -p <priority> | Встановлює альтернативу для поточного користувача | alts -u -n java -p 3000 |
sudo alts -s -n <name> -p <priority> | Встановлює системний default | sudo alts -s -n java -p 3105 |
alts -u -n <name> | Скидає користувацьке перевизначення до системного default | alts -u -n java |
Опції командного рядка
| Опція | Опис |
|---|---|
-h | Вивести довідку |
-l[<name>] | Список програм або альтернатив для вказаної програми |
-t <name> | Показати цільовий бінарник для програми |
-u | Користувацьке перевизначення (default для не-root) |
-s | Системне перевизначення (default для root) |
-n <program> | Назва програми для перевизначення |
-p <priority> | Пріоритет альтернативи (число) |
Примітка: Юзерські налаштування зберігаються у
~/.config/libalternatives/і мають найвищий пріоритет. Системні налаштування зберігаються у/etc/libalternatives/.
Важливо: Пріоритети визначаються пакетами у конфігураційних файлах
/usr/share/libalternatives/<name>/<priority>.conf. Користувач може вибрати лише існуючий пріоритет, а не довільно вказати шлях до бінарника.
Висновки
libalternatives - це символічний крок openSUSE у напрямку сучасної архітектури дистрибутивів. Він вирішує конкретну проблему сумісності зі снапшотами, яка критична для image-based систем типу MicroOS.
Поточний статус у openSUSE
Згідно з офіційною документацією, проекту пропонує три стратегії для мейнтейнерів пакетів:
- Міграція на
libalternatives- для ключових пакетів (Java, Node.js тощо) - Використання
Provides/Conflicts- для взаємовиключних пакетів - Залишити
update-alternatives- якщо альтернативи не підходять
На практиці пакети мігрують поступово. Java вже перейшла на libalternatives, інші знаходяться в процесі.
Важливо:
update-alternativesнікуди не зникне і залишиться доступним у openSUSE. Проте, для ключових пакетівlibalternativesпоступово стає стандартом.
Поширення поза openSUSE
Поза openSUSE ситуація стабільна. update-alternatives залишається де-факто стандартом:
- Вбудований у Debian Policy
- присутній у RHEL/CentOS
- Використовується у Fedora
Навряд чи інші дистрибутиви підуть шляхом SUSE в найближчому майбутньому.
Швидка шпаргалка
# Перегляд усіх зареєстрованих програм
alts -l
# Перегляд усіх альтернатив для java
alts -l java
# Перегляд поточної альтернативи для java
alts -t java
# Встановлення для поточного користувача (вибираємо пріоритет 3000)
alts -u -n java -p 3000
# Встановлення системного default (потрібен sudo)
sudo alts -s -n java -p 3105
# Скидання до системного default (видаляє користувацьке перевизначення)
alts -u -n java
# Перевірка, яка версія java насправді запускається
alts -t java
java -version
# Перегляд конфігураційних файлів для java
ls -la /usr/share/libalternatives/java/
cat /usr/share/libalternatives/java/3000.conf Примітка: Щоб дізнатися доступні пріоритети для програми, використайте
alts -l <name>. Пріоритети відображаються у форматіPriority: XXXX.