Nikolay Vasiliev Sideways notes

Один на один с debian

По долгу службы мне пришлось работать с ubuntu, линукс довольно популярный и простой. От debian ей досталась система пакетов. Этот пост дает все необходимые знания для начала работы с ним.

Первая команда

$ sudo apt-get update

Скорее всего, любой туториал по установке пакетов в ubuntu начинается с этой команды. Она обновляет список доступных для установки пакетов.

Первое, на что стоит обратить внимание. Работа с системой пакетов требует привелегий суперпользователя.

Второе. Установка пакетов может привести к потере системой (или ее части) работоспособности.

Операция apt-get update практически безвредна. Она только обновляет список доступных для установки пакетов.

apt-get хранит все доступные для установки имена и версии пакетов. Если у пакета появилась новая версия, чтобы ее установить, нужно сначала выполнить apt-get update.

Установка пакета

Рассмотрим установку пакета на примере mercurial.

$ sudo apt-get install mercurial

Команда apt-get install, как можно догадаться, устанавливает пакет. В данном случае - mercurial, клиент для одноименной системы контроля версий.

Эта команда изменит состояние вашей системы. В нашем случае появятся необходимые бинарники в /ust/bin, чтобы мы могли запускать команду hg, библиотеки, конфигурационные файлы и так далее. apt-get это no-brainer: предполагается, что он просто делает то, что от него просят.

Про посторонние эффекты при установке пакетов я расскажу несколько позже :)

Примерный алгоритм работы команды apt-get install.

  1. Уточнение списка пакетов - добавление всех зависимостей
  2. Проверка, что все пакеты могут быть установлены (есть в каком-нибудь репозитории)
  3. Скачивание пакетов
  4. Установка пакетов один за одним (в порядке разрешения зависимостей, более общие вперед).

Процесс установки отдельного пакета:

  1. Распаковывание пакета (пакет - это архив)
  2. Создание каталогов
  3. Копирование файлов
  4. Запуск postinstall скриптов (конфигурационные: создание пользователей, файлов, специфичных для машины и так далее)

Проверить, что пакет установлен

Чтобы убедиться, что мы действительно установили пакет, и что его версия соответствует ожиданиям, можно выполнить следующую команду:

$ dpkg -l mercurial
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Description
+++-==============================-==============================-============================================================================
ii mercurial 2.0.2-1ubuntu1 easy-to-use, scalable distributed version control system

dpkg - это дебиановский установщик пакетов. Он ничего не знает о репозиториях, он просто устанавливает скачанный пакет (и запоминает, что он его установил).

dpkg -l без дополнительных параметров выведет вообще все установленные в системе пакеты. Соединив его с grep, можно посмотреть выборочные пакеты.

$ dpkg -l | grep mercurial
ii mercurial 2.0.2-1ubuntu1 easy-to-use, scalable distributed version control system
ii mercurial-common 2.0.2-1ubuntu1 easy-to-use, scalable distributed version control system (common files)

Установка определенной версии пакета

Версию пакета можно указать явно (по умолчанию, apt возьмет самую новую из репозитория).

$ sudo apt-get install package=1.0.53

Формат такой: _имя пакета_=_версия_

Таким образом можно понизить версию, т.е. сделать downgrade. Это потенциально опасная операция, если пакет зависит от состояния машины. Например, если требуется определенная версия схемы базы данных.

Установка пакета из файла

Если пакета нужной версии нет в репозитории (например, она только что собрана), пакет можно установить прямо из *.deb файла. Для этого нужно выполнить:

$ sudo dpkg -i package.deb

Утилита dpkg не устанавливает зависимости пакета автоматически; именно эта утилита вызывается apt-get при установке каждого отдельного пакета.

Если не все зависимости пакета разрешены, он остается недоконфигурированным - то есть, postinstall скрипты не отрабатывают, но файлы уже скопированы. В таких случаях dpkg пишет, какими должны быть дальнейшие действия.

Как правило, нужно доустановить недостающие пакеты, вот такой командой:

$ sudo apt-get install -f

После установки всех зависимостей, будет запущена конфигурация устанавливаемого пакета.

Удаление пакета

Удаление пакета делается аналогично установке:

$ sudo apt-get remove mercurial

Эта операция требует sudo, а также несколько более сложная, чем установка.

Полное удаление пакета

При удалении пакета с помощью apt-get remove, конфигурационные файлы не удаляются. При повторной установке фаза конфигурации пакета пропускается. Это не всегда является желаемым поведением, чтобы удалить вообще все файлы, принадлежащие пакету, можно воспользоваться командой

$ sudo dpkg -P package

Эта команда также удалит все упоминания о том, что пакет был когда-то установлен в системе. То есть, до dpkg -P пакет виден в выдаче dpkg -l как удаленный, а после - его там просто нет.

Просмотреть, какие файлы "принадлежат" пакету

Иногда требуется узнать, какие именно файлы были установлены из пакета. Например, найти конфигурационные файлы сервера mysql. Для этого нужно выполнить

$ dpkg -L mysql

Репозитории пакетов

Информация о репозиториях, с которыми умеет работать apt-get, хранится в файле:

/etc/apt/sources.list

Он состоит из записей вида:

deb http://ru.archive.ubuntu.com/ubuntu/ trusty main 

Здесь указаны:

  • тип репозитория (deb - бинарные пакеты, deb-src - исходные коды)
  • URL репозитория
  • тип целевой системы (кодовое имя релиза), архитектура (i386, amd64)
  • бранч (группа пакетов, например stable/testing/unstable)

Редактируя файл /etc/apt/sources.list, можно управлять списком репозиториев. Если надстроек становится много, их выносят в отдельные файлы того же формата, и помещают в каталог /etc/apt/sources.list.d/.

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

Список доступных для установки версий пакетов

Для того, чтобы узнать, какие в принципе версии пакета доступны для установки, можно выполнить команду

$ apt-cache policy mercurial
mercurial:
Installed: 2.0.2-1ubuntu1
Candidate: 2.0.2-1ubuntu1
Version table:
*** 2.0.2-1ubuntu1 0
500 http://sata-raid10.clouds.archive.ubuntu.com/ubuntu/ precise/universe amd64 Packages
500 http://mirror.yandex.ru/ubuntu/ precise/universe amd64 Packages
100 /var/lib/dpkg/status

В выдаче команды присутствует следующая информация:

  • какая версия сейчас установлена;
  • какая будет установлена по умолчанию (если выполнить apt-get install без явного указания номера версии);
  • из какого репозитория была установлена текущая версия пакета;
  • из каких репозиториев могут быть установлены другие версии пакета.

Некоторые тонкости

Посторонние эффекты при установке пакетов

Во-первых, при установке пакета с помощью apt-get, устанавливаются все его зависимости. Чтобы избежать сюрпризов, apt-get в интерактивном режиме указывает, какие дополнительные пакеты будут установлены, и сколько они займут места на жестком диске.

Во-вторых, так как пакеты включают в себя конфигурационные скрипты, возможны любые посторонние эффекты. С учетом того, что выполняется этот код от имени root, любое неосторожное движение может навредить системе, как, например, ошибочное удаление системных файлов. В том числе по этой причине ubuntu строго следит за пакетами в своем репозитории - чтобы там не было вредных пакетов.

Особенности удаления зависимых пакетов

Сложности могут возникнуть, когда вы удаляете пакет, от которого зависят другие пакеты. Возможны такие сценарии:

  1. От вашего пакета никто не зависит - просто удаляется
  2. От пакета Х зависит другой пакет Y. apt скажет, что Y будет также удален. Потребуется подтверждение вводом с клавиатуры.
  3. От пакета Х зависит другой пакет Y, но пакет X может быть заменен пакетом Z. apt скажет, что X будет удален, а Z установлен. Потребуется подтверждение вводом с клавиатуры.

Последний случай достаточно редок, и тем большим сюрпризом он окажется. Дело в том, что debian поддерживает зависимость типа provides (пакет "выступает в качестве" другого).

Package A
provides: C

Package B
Provides: C

Package D
depends: C

В этой ситуации непонятно, какой именно пакет возьмется при установке D, ведь в качетсве C можно взять и A, и B.

При этом, если установлены A и D, и удалить A, то на его место придет B (если есть пакет, зависящий от C), а D останется в системе.

Резюме

В этом посте перечислены основные команды для работы с системой пакетов ubuntu:

  • установка
  • удаление
  • управление репозиториями
  • получение информации о пакетах в системе