Використовуємо apt pinning для закріплення пакетів в debian і ubuntu - записки it фахівця

Досить часто при роботі з Linux-системами виникає потреба у встановленні пакунків в версії відмінно від тієї, що знаходиться в репозиторіях. Найчастіше для цих цілей використовується ручна установка потрібної версії пакету з подальшою заморожуванням (при необхідності) або складання пакета з вихідних. У той же час в заснованих на Debian дистрибутивах існує штатна система закріплення пакетів APT Pinning, використання якої більш переважно, тим більше що працювати з нею зовсім нескладно.
Перш за все давайте розберемося, чому використовувати ручну установку пакетів небажано. Звичайно, якщо мова йде про якусь окрему бібліотеці для внутрішніх потреб, скажімо для збірки PostgreSQL від 1С, то немає ніякого сенсу городити город, можна сміливо поставити пакет вручну і благополучно про нього забути. Зовсім інша справа якщо ви таким чином встановіть будь-яку публічну службу, скажімо, веб-сервер Apache або інтерпретатор PHP.
У наш час загальної доступності інтернету і розвинених каналів комунікацій інформація про уразливість широко поширюється в найкоротші терміни, що змушує відповідально підходити до питання своєчасного оновлення ПЗ. У випадку з ручною установкою, а тим більше складанням з початкових кодів, вся відповідальність за подальшу підтримку лежить повністю на вас. Вам буде потрібно самостійно відстежувати вихід оновлень і також самостійно підтримувати актуальне ПО на своєму сервері.
Як показує практика - будь-яка вразлива система рано чи пізно буде зламана. Причому дізнатися про це ви можете в останню чергу, коли вашого хостера або провайдеру прийде претензія на те, що ваш сервер розсилає спам, бере участь в DDoS-атаці або займається ще який-небудь непристойної діяльністю.
Чим же хороший APT Pinning? Ця технологія заснована виборі джерела пакетів на підставі заданих вами переваг. Тобто цілком реально ставати підключити репозиторії з потрібними версіями пакетів, правильно налаштувати переваги і отримувати всі оновлення пакетів звідти використовуючи штатні механізми. Це відразу знімає цілий пласт проблем, пов'язаних з підтримкою, якщо потрібний пакет отримує поновлення ваша система теж їх отримає.
Список репозиторіїв зберігається в /etc/apt/sources.list. якщо ми відкриємо це файл, наприклад, в Debian 8, то побачимо наступне:

Як неважко помітити даний набір належить до актуального на поточний момент дистрибутива Debain 8 "Jessie", для інших випусків слід замінити jessie на кодове ім'я іншого дистрибутива.
Крім кодових імен Debian дозволяє використовувати клас релізу: stable, oldstable, testing, unstable. Поточний дистрибутив - це stable. попередній - oldstable. розробляється - testing. нестабільний (sid) - unstable. Однак на практиці такі позначення не використовуються, тому що якщо у вас замість jessie вказано stable. то з виходом наступного стабільного дистрибутива - stretch - відбудеться автоматичне оновлення на нього, що на робочих серверах може привести до несподіваних наслідків. Хоча якщо ви ентузіаст, то можете прописати всюди testing і бути постійно на передньому краї прогресу.
В Ubuntu набір репозиторіїв виглядає трохи інакше:

У підсумку список основних репозиторіїв можна привести до виду:
В Ubuntu версія дистрибутива задається тільки по кодовому імені, в нашому випадку це trusty - Ubuntu 14.04 LTS (Trusty Tahr).
Додати нові репозиторії можна двома способами: дописати їх в основний файл /etc/apt/sources.list. або створити новий файл з розширенням .list в папці /etc/apt/sources.list.d. наприклад, precise.list для репозиторіїв Ubuntu 12.04 і т.п. всі файли з цієї папки з правильним розширенням будуть автоматично підключені до списку джерел.
Після того як ви додали нові репозиторії потрібно оновити список пакетів:
Тепер саме час розібратися, як відбувається вибір пакета для установки. Для цього можна виконати команду:
Давайте уважно розглянемо скріншот нижче, де ми виконали зазначену команду для пакета Nginx:

Значення ваги пріоритету можуть бути наступними:
- P> = 1000 - пакет буде встановлений, навіть якщо це призведе до зниження версії вже встановленого пакету
- 990 <= P <1000 - пакет будет установлен, если не установлена более новая версия
- 500 <= P <990 - пакет будет установлен, если нет пакета принадлежащего к целевому выпуску или не установлена более новая версия
- 100 <= P <500 - пакет будет установлен, если нет кандидатов из других источников или установленного пакета более новой версии
- 0
- P <0 - пакет не будет установлен ни при каких условиях
- P = 0 - невизначений стан, не використовується
Використовувати вагу понад 1000 слід з обережністю, особливо якщо переваги включають відбір по масці, в цьому випадку ви можете без запиту провести зниження відразу цілого набору пакетів (по залежностям), що може призвести до несподіваних результатів.
Вага від 990 до 1000 також виробляє оновлення вже встановлених пакетів, але тільки в разі підвищення їх версії. Небезпека безконтрольного застосування цих двох режимів полягає в тому, що можуть бути поламані залежності, і в зв'язку з цим видалені, сторонні пакети, що може привести до повної або часткової непрацездатності системи.
Окремо зупинимося на відмінностях між вагою в діапазоні 500 - 990 і 990 - 1000.
Так при вазі від 500 і вище новий пакет буде завжди встановлений і замінить вже існуючий пакет якщо дія буде явно задано користувачем. Таким чином команди:
оновлять пакет або набір пакетів до найновіших версій при вазі від 500 і вище. Наприклад, у нас на Debian 7 виявлено apache 2.2, додамо репозиторії від Debain 8 і подивимося кандидата на установку:

Різниця полягає в понятті цільового випуску. який за замовчуванням не заданий, тому поведінка системи з вагами від 500 до 1000 буде однаковим. Щоб задати цільової випуск створимо в папці /etc/apt/apt.conf.d порожній файл без розширення, скажімо, default і внесемо в нього такий рядок:
Це встановить в якості цільового встановлений випуск Debian 7. Перевіримо що буде тепер:


У самому файлі слід розмістити один або кілька наборів наступних директив:
Ім'я пакета може бути задано як цілком, так і по масці, наприклад, apache2 *. Допускається також вказівку кількох імен через пробіл.
В якості опції прикріплення можуть виступати джерело пакетів, версія і їх походження. Наприклад, наступний набір директив закріпить Perl на рівні лінійки 5.10, а заданий вага пакета 1001 дозволить знизити вже встановлену версію (при необхідності).
А ця конструкція вказує отримувати пакети sqiud3 зі сховищ example.com. наприклад, якщо вам потрібно використовувати спеціальну збірку пакету і не допускати його заміни штатним, навіть якщо він буде новіше.
І нарешті прив'язка до певного випуску, наприклад всі пакети по масці apache2 * брати з репозиторіїв випуску wheezy:
Для Debian допустимо також використовувати конструкцію:
Для Ubuntu значення обох ключів n і a збігається і має містити кодове ім'я релізу.
Щоб не бути голослівними розглянемо кілька практичних сценаріїв.
Зниження версії пакетів
Найбільш часто потрібно знизити версію Apache з 2.4 до 2.2, наприклад, для потреб 1С підприємства. Тому перш за все в систему слід додати репозиторії від попереднього випуску, який містить потрібну версію Apache, це wheezy для Debian або precise для Ubuntu. Далі можна піти двома шляхами, наприклад, задати вагу 1001 і провести заміну потрібних пакетів:
Це потенційно небезпечна операція, тому перед тим як проводити встановлення слід виконати її тестування:
Якщо висновок не поміщається в екран, то його слід перенаправити утиліті less:
Після чого уважно вивчаємо висновок. Найбільш пильну увагу приділяємо пакетам, які будуть видалені або замінені більш старими версіями.

Для того, щоб видалити пакети спочатку потрібно отримати їх список, для цього служить команда dpkg -l з подальшим відбором на ім'я пакета.

Встановлені пакети видаляємо командою:
Також можна видалити і всі налаштування пакетів, для цього знову виконайте
Однак врахуйте, що дана операція знищить всі налаштування і дані відносяться до пакунка, у випадку з MySQL або PostgreSQL це призведе до повної втрати даних, тому попередньо зробіть копії потрібного дані та настройки.
Після чого можна встановити пакет, попередньо його протестувавши.

Підвищення версії пакетів
Теоретично, процес підвищення нічим не відрізняється від зниження. Підключаємо репозиторій, встановлюємо переваги і оновлюємо пакети. Але на практиці даний процес стикається з безліччю труднощів. Основним ускладненням стає те, що пакети нового випуску зібрані в середовищі нових бібліотек, в зв'язку з чим потребують оновлення багатьох залежностей, ті в свою чергу тягнуть за собою свої залежності і т.д. і т.п.
Взагалі правильним способом підвищення пакета є його збірка в оточенні поточного дистрибутива з вихідних кодів сховища deb-src від нового випуску. Однак цей метод виходить за рамки даної статті.
Ми ж покажемо вам практичний приклад спроби підвищення версії пакету. Перш за все, підключивши репозиторії від більш свіжого випуску, не забудьте вказати цільової випуск або знизити їх пріоритет, наприклад, наступними директивами:
Добре, дистрибутиви додали, пріоритети виставили, кандидатів перевірили, начебто все нормально. Спробуємо встановити пакет в тестовому режимі:


Ну ось, начебто все додано, як бачимо в список переваг потрапили найнесподіваніші пакети (а ми хотіли тільки оновити Apache):

Тестуємо установку і бачимо досить несподіваний результат:
