Цель этого поста: показать технику отладки в debian/ubuntu, связанную с "поиском первоисточника" в системном конфигурационном файле.
Тестовый пример: после долгих издевательств над tar.gz копией установленной ОС и после её восстановления и установки апдейтов мы получаем сообщение:
update-initramfs: Generating /boot/initrd.img-4.15.0-54-generic
W: initramfs-tools configuration sets RESUME=/dev/mapper/U1563304817I0-swap
W: but no matching swap device is available.
I: The initramfs will attempt to resume from /dev/dm-1
I: (/dev/mapper/foobar-swap)
I: Set the RESUME variable to override this.
Цель: понять, откуда это значение (U1563304817I0) пришло и как его правильно поменять. Это первый попавшийся пример, не особо интересный сам по себе, но удобный, чтобы показать практические методы работы с Linux.
Шаг номер 1: Откуда пришёл RESUME?
# cd /etc
# grep -r RESUME
initramfs-tools/conf.d/resume:RESUME=/dev/mapper/U1563304817I0-swap
Мы рекурсивно (-r
) ищем упоминание этой переменной в каталоге /etc (там, где большинство конфигов). Мы находим conf.d сниппет, который явно используется пакетом initramfs-tools.
Откуда этот сниппет?
Есть три варианта:
- Магический артефакт (кто-то положил и забыл)
- Конфиг из пакета
- Конфиг, сгенерированный каким-то скриптом из системных пакетов
Проверяем №2 (как самый простой):
dpkg -S initramfs-tools/conf.d/resume
dpkg-query: no path found matching pattern *initramfs-tools/conf.d/resume*
dpkg -S
позволяет нам поискать по базе установленных файлов и найти к какому пакету файл относится. Вот пример удачного поиска:
dpkg -S resolv.conf
manpages: /usr/share/man/man5/resolv.conf.5.gz
systemd: /lib/systemd/resolv.conf
Возвращаемся к нашей задаче: файл initramfs-tools/conf.d/resume
не устанавливается в систему из пакета. Может быть он генерируется в postinst/preinst скрипте пакета? Проверяем версию номер 3.
# cd /var/lib/dpkg/info/
# grep -r initramfs-tools/conf.d/resume *
initramfs-tools-core.postrm: rm -f /etc/initramfs-tools/conf.d/resume
В каталоге /var/lib/dpkg/info/
лежат распакованные версии всех "метафайлов" пакетов (скрипты установки/удаления, описания пакетов и т.д.). Удивительно, но этот файл удаляется в postrm (при удалении) пакета initramfs-tools-core. Посмотрим содержимое его postinst… Ничего, касающегося conf.d директории.
Давайте посмотрим на файлы из состава пакета initramfs-tools-core
.
# dpkg -L initramfs-tools-core
...
/usr/share/initramfs-tools/hooks/resume
...
Команда dpkg -L
позволяет посмотреть все файлы, которые есть в системе от указанного пакета. Я выделил интересный для изучения файл. Изучение файла показывает как эта переменная используется, но не отвечает откуда он появляется.
debconf
Получается, это чей-то артефакт. Чей? Перед тем, как нырять в инсталлятор, глянем ещё в одну важную инфраструктуру Debian — ответы на вопросы. Каждый раз, когда пакет задаёт вопрос, и во многих случаях, когда он вопроса не задаёт, но использует вариант по-умолчанию, и вопрос, и ответ фиксируются в специальной базе в Debian, которая называется debconf. Мы можем посмотреть на базу ответов (и даже выставить их до установки самого пакета — debconf-set-selections
), для этого нам потребуется утилита debconf-get-selections
из состава debconf-utils
. К сожалению, ничего интересного не нашлось: (debconf-get-selections |grep -i resume
вернул пусто).
debian-installer
У установщика есть своя база ответов на вопросы: /var/log/installer/cdebconf/questions.dat
. К сожалению, там тоже нет ни слова про наш resume.
Зато рядом есть логи, в т.ч. syslog, куда пишется весь лог инсталляции. Там упоминается пакет base-installer, и на его странице мы можем видеть ссылку на сырцы.
Внутри них мы с лёгкостью находим ответ на наш вопрос:
resume="$(mapdevfs "$resume_devfs")"; then
...
if [ "$do_initrd" = yes ]; then
...
resumeconf=$IT_CONFDIR/resume
....
echo "RESUME=$resume" >> $resumeconf
mapdevfs — это утилита с понятным назначением, а интересная нам функция это get_resume_partition
, которая читает /proc/swaps и выбирает там самую большую. Swap же у нас приходит от partman'а.
Ответ на наше тестовое задание: файл создаётся инсталлятором в /target'е в момент установки, т.е. мы говорим про well-known, но артефакт. В существующих в системе пакетах нет никого и ничего, чтобы меняло этот файл.
Подводя итог
- dpkg и debconf — основные методы для поиска поставщиков файлов.
- поиск в /var/lib/dpkg/info позволяет увидеть операции над файлами на этапе установки.
- Установщик может создавать файлы-артефакты, которые потом никем никогда не меняются (кроме пользователя), и это можно увидеть в коде установщика.
Комментарии (23)
Andrey_Rogovsky
23.07.2019 20:13— Сынок, у тебя опять мусор в комнате?
— Мам, отстань, это — артефакты!amarao Автор
23.07.2019 22:56+3— Мы уже много раз обсуждали, что все артефакты должны помещаться в централизованное хранилище с заданной retention policy.
Cenzo
23.07.2019 21:54Эх, когда же будут по дефолту конфиги по типу git, чтобы было ясно, кто, откуда, когда и какую строчку. Сохранил как шпаргалку, так как часто подобное приходилось делать в RPM-based.
оператор ЭВМ
Вспомнил свои корочки оператора ЭВМ на втором курсе универа, вытер скупую слезу.evg_krsk
24.07.2019 06:18Отчасти эту проблему решает etckeeper — он умеет на каждое изменение в /etc писать в commit message, какие пакеты были удалены/установлены (как для deb так и для rpm). Кто конкретно создал файл он не покажет, но поможет с точностью до дня/пакета установить причастных.
gecube
24.07.2019 08:20отчасти эту проблему решает любой SCM (да даже ансибл в принципе, не говоря уже о нормальных системах — chef/puppet/salt), тем более, если в нем (в конф файле) пришивается заголовок, что все ручные изменения файла будут перетерты. Но, к сожалению, SCM и пакетный менеджер иногда тоже устраивает драку за то, чьи правки более верные )
Cenzo
25.07.2019 03:53Ansible не решит части проблем, если при апдейте системы приползёт новый системный скрипт, который внезапно добавит или изменит конфиг, который до этого Ansible вообще не трогал. Но etcd/consul выглядит для конфигов более удобным, чем Ансибл, хотя проблемы остаются те же, все системные конфиги в него не запихаешь. (Как девелопер сейчас смотрю на эту кухню более со стороны)
Gamliel_Fishkin
24.07.2019 05:55update-initramfs: Generating /boot/initrd.img-4.15.0-54-generic
Судя по номеру ядра, это Ubuntu 18.04 Bionic Beaver — в Debian 10.0.0 Buster ядро 4.19.amarao Автор
24.07.2019 11:12Ага. Но пост как раз про дебиановскую подсистему, которая в убунте до сих пор основная (сколько бы они не пытались своё придумать).
gecube
Очень интересное приключение.
Занятно, а разработчики дебиан почему не сделали единый интерфейс для создания настроенных файлов? Или это в принципе на этой стадии установки системы невозможно ?
amarao Автор
Такой интерфейс есть, называется conffiles. К сожалению, в общем случае provenance (происхождение) файла конфигурации очень трудно установить административными методами, потому что иногда эти файлы генерируются утилитами софта (я смотрю на тебя, pg_cluster). В теории такая система была бы крутой, но… Поверьте мне, в мире update-initramfs/update-grub есть куда большие ужасы, чем отсутствие единой базы конфигов… Там гигантские стопки баша, вызвающие Си, который вызывает баш, который вызывает Си… Боль, легаси и привет из конца 90ых, когда это было "ок.
gecube
по мне вообще весь deb как принцип ущербен. Чего стоит миграции баз между версиями в пост-инсталл mysql пакета. Блин, парни, а ничего, что это не должно никогда на автомате производиться?
Я уж не говорю, что транзакционность установки пакетов в rpm-based на порядок лучше, чем в дебиан (видели необходимость делать apt install с ключом force или dpkg reconfigure, если что-то пошло не так?)
По идее может спасти этот мир CoreOS с докеризованными приложениями… но нет...
Самое обидное в этой истории, что приходится двигаться за большинством… и тут внезапно в продакшене оказывается убунта… и хорошо, если еще LTS, ога.
Magister7
Хм, а мне вот наоборот, удобно что миграция версий происходит автоматически. Меньше ручной работы — обновил пакет, все что надо перезапустилось, если пакет использует debconf и я руками ничего не исправлял, то и конфиг обновился сам, и все — все работает.
Минимум ручных операций.
В чем тут проблема? Пакет же сам не прилетит с новой мажорной версией, а если я сам это доклад то явно и базы обновить хочу.
Транзакционность — оно то да, но я вот даже не вспомню когда у меня что-то ломалось по этой причине. Бывало что пакет остаётся half-installed из-за ошибки в postinst-скрипте, но тут можно найти причину и поправить — скрипты лежат себе распакованные на своем месте, и продолжить процесс через
apt -f install
JTG
> apt install с ключом force
Особенно «полезен» этот совет, когда в процессе установки заканчивается место на /boot
www.linux.org.ru/forum/general/11955554
askubuntu.com/questions/345588/what-is-the-safest-way-to-clean-up-boot-partition/430944#430944
amarao Автор
Удивительные приключения цитаты при квотировании...
Сказали
apt -f install
, в квоте появилосьapt
с ключомforce
. Хотя man страница говорит, что-f
— это--fix-broken
.А дальше с удобной цитатой удобно спорить.
DaemonGloom
Да нет, там gecube именно про ключ force сказал. Ошибся, видимо. Или не так понял параметр.
amarao Автор
А, пардон. Особенности древовидного чтения.
gecube
ну, может я и ошибся ) по памяти писал, а на абсолютное знание дебиан систем я не претендую )
gecube
Да, кстати, на ситуации по ссылкам я попадал. И как-то с грехом пополам их решал.
NetBUG
А единая база конфига на реальной, работающей системе (т.е. у нас есть несколько сотен пакетов — включая служебные, которые в этой системе работают минимум два релиза, т.е. есть legacy-параметры) приводит… внезапно, к появлению свалки типа «реестр».
Несколько могло бы помочь решение с разделением полномочий (т.е. один пользователь пишет в одну ветку, одно приложение пишет в одну ветку), которого так не хватает Windows Registry. Но проблемы бессмысленных, не читаемых никем параметров это не снимает.
Если каждому параметру добавить last_access_time — эта помойка ещё и тормозить будет.
gecube
Ага. А в распределенных системах роль такой базы выполняет Consul, который при неаккуратном обращении так же превращается в свалку неактуальных k/v значений. Но это судьба любого стейтфул — рано или поздно превратиться в помойку.
amarao Автор
Наличие свалки определяется тем, является ли полученная конструкция жёсткой или нет. Теоретически, при должном фашизме, у нас может быть схема, которая позволяет отвечать на вопрос "кто отвечает за эту настройку?" и "когда это можно удалять?". Например, даже при многих своих недостатках, debian может сказать, когда конфиги приложения надо удалять и что именно "конфиг" (так называемый purge).
Но полноценная поддержка такого требует реального схемо-фашизма и проверки связности всех узлов графа. Может быть, кто-нибудь, когда-нибудь осилит такое. Пока что наслаждаемся креативным анархизмом.