Как удалить пакет в CentOS, не удаляя связанные с ним зависимости
Это странно, но такое иногда бывает нужно. Мне, например, потребовалось перейти с системной библиотеки libmysql на встроенную в PHP (MySQL Native Driver), т.е. ненадолго удалить одну из базовых библиотек PHP (php-mysql и php-mysqli), чего, конечно, испугались многие пакеты, имеющие PHP в зависимостях. Итак, похоже, yum не умеет удалять пакет без удаления его зависимостей, но мы обойдёмся и без yum.
Сначала опишу проблему более подробно на конкретном примере. Если в лоб попытаться установить новый нужный пакет (например, yum install php55w-mysqlnd ), то менеджер пакетов yum будет ругаться на конфликт:
—> Processing Conflict: php55w-mysql-5.5.33-1.w6.x86_64 conflicts php55w-mysqlnd
Ок, а что если удалить сначала старый пакет? Сделаем yum remove php55w-mysql и увидим, что вслед за ним удалиться phpMyAdmin:
—> Package php55w-mysql.x86_64 0:5.5.33-1.w6 will be erased
—> Processing Dependency: php-mysqli for package: phpMyAdmin-4.0.10.14-1.el6.noarch
—> Processing Dependency: php-mysql >= 5.2.0 for package: phpMyAdmin-4.0.10.14-1.el6.noarch
—> Running transaction check
—> Package phpMyAdmin.noarch 0:4.0.10.14-1.el6 will be erased
Это нехорошо. Но пакет всё-таки можно удалить без удаления зависимостей.
Для этого сначала надо найти полное имя пакета: rpm -qa | grep «php55w-mysql»
В ответ получим что-то типа: php55w-mysql-5.5.33-1.w6.x86_64
Теперь, используя это имя, действуем: rpm -e —nodeps «php55w-mysql-5.5.33-1.w6.x86_64»
Никаких подтверждений у вас не спросят, пакет сразу и бесповоротно удалится.
Теперь снова попробуем установить новый пакет: yum install php55w-mysqlnd
Установка пойдёт нормально (конфликтовать-то новому пакету уже не с чем), разве что в процессе установки менеджер пакетов yum вам пожалуется, что без его ведома кто-то нехороший нарушил зависимости:
Warning: RPMDB altered outside of yum.
** Found 2 pre-existing rpmdb problem(s), ‘yum check’ output follows:
phpMyAdmin-4.0.10.14-1.el6.noarch has missing requires of php-mysql >= (‘0’, ‘5.2.0’, None)
phpMyAdmin-4.0.10.14-1.el6.noarch has missing requires of php-mysqli
Однако работать всё будет. В том числе phpMyAdmin, который у нас НЕ удалялся.
Удаление пакета без учёта зависимостей
Имеем Debian 9 с Gnome 3.22.3
Вместе с гномом в систему устанавливается пакет Caribou — виртуальная клавиатура этой оболочки по умолчанию.
В данной ситуации эта виртуальная клавиатура оказалась не нужна, т.к. требовалась другая — OnBoard.
Проблема была в том, что Caribou вылезала там, где не нужно и блокировала ввод с OnBoard. Требовалось Caribou либо отключить совсем, либо вообще удалить.
Но это всё так — исходные условия.
Проблема, по сути в том, что
по зависимостям удаляют и gnome-core вместе со всем рабочим окружением Gnome3, что в данном случае совершенно неприемлемо.
Теперь о том, как это сделать так, чтобы удалить Caribou и при этом оставить gnome-core.
Зависимости пакетов приложений в линуксах вообще нужны для того, чтобы вы, при установке какого-либо пакета приложения не выискивали все необходимые для его функционирования компоненты вручную, а выполняя одну короткую команду
apt-get install packagename
получали всё необходимое сразу.
Так же зависимостями управляются пакеты и при удалении: если данным пакетом больше ни одна программа не пользуется, то зачем ему занимать место на диске и вообще засорять систему?
Вообще — зависимости, за исключением некоторых гиковских дистрибутивов, это то, что, в первую очередь, отличает линуксы от виндовсов.
Ведь, именно благодаря зависимостям, решаются такие фичи линухов, как совместное использование разделяемых библиотек, совместимость версий пакетов, совместное обновление используемого ПО и многие прочие задачи.
Если коротко, то функциональность пакетных менеджеров основана как раз на удовлетворении зависимостей пакетов. И, если часть установленных в системе пакетов имеет неудовлетворённые зависимости, то система в целом более подвержена сбоям, снижается её безопасность и целостность, накапливается программный мусор и прочие проблемы. То есть, благодаря зависимостям пакетов и взаимодействию с ними пакетных менеджеров ваша система остаётся удобной, стабильной и быстрой.
Это, если коротко.
Более подробно о зависимостях, вы, конечно, можете самостоятельно нагуглить в интернетах, но я вам скажу просто: зависимости — это очень удобный и полезный функционал пакетных менеджеров, который просто так, не разбираясь в вопросе и не владея предметом, игнорировать однозначно не стоит. Поэтому, прежде чем выполнять нижеизложенные действия, подумайте и не делайте этого, если вы не вполне понимаете, что вы делаете.
Вообще, таким методом, который я описываю сейчас можно удалить любой пакет из системы, не затрагивая зависимые от него пакеты.
В данном случае разговор только о Caribou, который мы будем использовать для примера.
выяснили, что он тянет за собой и gnome-core, который тянет за собой вообще всю gnome-shell.
Исходя из того, что все ПМ в Debian (и его форках и потомках) в конечном итоге для управления пакетами (для непосредственного действия с пакетами) юзают dpkg, делаем вот что:
dpkg --force-depends -r packagename
Но в данном случае (возможно, это зависит от версии самого dpkg) он у меня ругнулся и удалять карибу не захотел (дебиан вообще славится своей стабильностью именно благодаря сильной связанности пакетов зависимостями и вероятно поэтому выпиленной этой опцией в данной версии).
Как вариант, можно попробовать
dpkg --ignore-depends=packagename -r packagename
Но, у меня не сработало и это.
Итак, было решено уже выпиливать неугодный пакет вручную (до первого apt update && apt upgrade).
Но всё-таки, я хотел провести операцию более цивилизованным образом.
2. У dpkg где-то записаны все установленные пакеты и их зависимости в одном месте. Нам нужно выяснить путь и имя этого конфига.
Сей конфиг лежит в Debian 9 в пути
/var/lib/dpkg/
и называется status
То бишь, если мы отредактируем файл /var/lib/dpkg/status соответствующим образом, то, тем самым мы можем вручную разрешить зависимости любого пакета.
Это действие является весьма грязным хаком и крайне не рекомендуется для применения, в особенности для неопытных пользователей.
Перед началом данной операции обязательно сохраните его копию в то место, где вы его случайно удалить не сможете — создайте из под рута директорию в корне с нестандартным именем и правами только для рута. Кроме того, нам потребуется создать ещё один файлик (далее — tempfile) со списком зависимостей — он может быть в любом удобном вам месте и формате. Лучше, конечно, каждый зависимый пакет писать с новой строки (потом проще читать скриптом).
Package: packagename
Status: install ok installed Статус пакета в системе
Priority: optional
Section: gnome
Installed-Size: 1856 Размер пакета в байтах
Maintainer: Debian GNOME Maintainers
Architecture: amd64
Version: 3.22.0-1 Версия пакета
Depends: Тут перечислены зависимости пакета через запятую, прямо вот так: libc6 (>= 2.14), libcairo2 (>= 1.2.4), libfontconfig1 (>= 2.11), libfreetype6 (>= 2.2.1), И так далее. Нам, собственно эта секция и нужна .
Description: character map application
Characters is a simple utility application to find and
insert unusual characters.
Homepage: https://wiki.gnome.org/Design/Apps/PackageName
Выделенного этим цветом в файле нет Там вообще нет нелатиницы.
PackageName — ищем необходимые нам пакеты с этим упоминанием. Регистр имеет значение.
Как удобнее искать?
Проще всего сделать поиск по файлу. Например, в Gedit открываем данный файл, жмякаем Ctrl+F и вводим имя пакета (в моём случае это было ‘caribou’) — редактор подсветит все упоминания в файле вне зависимости от регистра.
Упоминания будут наверняка не в одном месте.
И тут два варианта: в заголовке или в списке зависимостей.
В первом варианте делаем так: вырезаем из списка зависимостей всё, что вы удалять при удалении ненужного пакета не желаете и вставляете это в tempfile, куда я сказал вам выносить зависимости.
Например, при удалении caribou в libcaribou в зависимостях было упоминание libc6 (>= 2.14), который я удалять не собирался, поэтому я вырезал из секции Depends его упоминание и воткнул в tempfile.
Запутанно, неправда-ли?
Всё просто: то, что хотим удалить одновременно с удалением целевого пакета — оставляем в зависимостях, а остальное — переносим в tempfile
Второй случай: упоминание целевого пакета есть в зависимостях другого нужного нам пакета, который мы оставить хотим.
Тут ещё проще: просто удаляем это упоминание, а имя пакета заносим в наш временный файлик.
Ещё раз повторю: перед началом этого действия создайте его копию в недоступном для детей месте.
После того, как вы отредактировали данный файл (в смысле — ‘status’, а он весьма объёмистый), его нужно сохранить в том же месте и выполнить в терминале
И «непокорный» пакет будет удалён.
Но у нас ещё остаётся проблема восстановления удалённого пакета обновлением. Вот тут-то нам и потребуется этот наш временный файлик.
Чтобы порешать эту проблему, нужно выполнить следующее действие со всеми зависимыми от удалённого пакетами:
echo "depends-packagename hold" | sudo dpkg --set-selections
Тем самым «заморозить» эти пакеты и запретить их обновление.
Для автоматизации этого процесса выполним вот такой скриптик:
uniq /path/to/tempfile > ./sorted _VAR=./sorted cat "$_VAR" | while read _LINE; do echo "$_LINE hold" | sudo dpkg --set-selections
И вот теперь мы можем быть уверены, что сей удалённый пакет в системе больше не появится, по крайней мере до тех пор, пока вы не изволите разморозить пакеты, перечисленные в tempfile и обновить их.
Заочно соглашусь, что данное решение может быть не самым правильным, с точки зрения философии ПМов и линухов вообще, но второй вариант у меня сработал.
Если у вас есть лучшие решения — поделитесь, но сильно тапками колотить меня не обязательно.