Apt pinning: namíchejte si vlastní Debian

14. 1. 2014
Doba čtení: 8 minut

Sdílet

Apt pinning je metoda, kterou je možné zásadně ovlivňovat chování balíčkovacího systému v Debianu a z něj vycházejících distribucí. Umožňuje udržovat balíčky v konkrétních verzích nebo pohodlně míchat různé distribuční větve či repozitáře třetích stran. Pokud pinning zvládnete, stanete se pánem balíčků.

Balíčkovací systém v Debianu funguje poměrně přímočaře. Prochází seznam zdrojů v souboru /etc/apt/sources.list a adresáři /etc/apt/sources.list.d/ z jednotlivých serverů načítá databázi balíčků, kterou si lokálně uloží. Pracuje pak s nejnovějšími verzemi balíčků, které na různých serverech najde. Ty porovná s nainstalovanými verzemi a dokáže nabídnout jejich aktualizaci.

Pokud jsme uživateli nejjednoduššího scénáře a máme v systému repozitář jedné větve Debianu, pak to funguje krásně. Ne vždy ale chceme sáhnout po nejnovější verzi všech balíčků a vyhovoval by nám jiný model. Typické je to třeba u míchání různých větví Debianu.

Pokud byste jednoduše vložili mezi zdroje repozitáře větví testing a unstable, balíčkovací systém by si všiml, že v některých repozitářích (těch s unstable) jsou novější verze a navrhl by vám aktualizaci celého systému. Pokud ale chcete z unstable jen některé balíčky (třeba novější verzi web serveru), musíte postupovat jinak.

Důležitá poznámka: Velmi často se setkávám s terminologickým problémem ohledně názvů větví stable (stabilní) a unstable (nestabilní). Tato slova neoznačují stabilitu ve smyslu dlouhého běhu Debianu bez havárie, ale ve smyslu změn verzí balíčků. Ve větvi stable se balíčky nemění (verze jsou stabilní) a naopak. Jednoznačnější pojmenování by tedy mohlo znít „statická“ a „pohyblivá“.

Volíme větev

Pokud chcete začít s mícháním větví, budete potřebovat balíčkovacímu systému sdělit, kterou větev si přejete preferovat a dát jejím balíčkům vyšší prioritu. To provedete tak, že vytvoříte soubor /etc/apt/apt.conf.d/00release a do něj zapíšete například:

APT::Default-Release "testing";

Můžete použít větev (stable, testing, unstable) nebo její současné jméno (wheezy, jessie, sid). Pamatujte ovšem na to, že jména se mění a posouvají (kromě sid), kdežto názvy větví zůstávají stejné.

Pokud jste takto zvolili preferovaný repozitář, můžete si do sources.list přidat další repozitáře. Protože jsme neudělali nic dalšího, balíčkovací systém bude o nových balících vědět, ale bude je vesele ignorovat, protože mají nižší prioritu než ty ze zvolené větve. Na první pohled se tedy nebude nic dít.

Důležitá poznámka: Při míchání větví postupujte velmi opatrně a sledujte, co po vás balíčkovací systém chce. Může se vám totiž stát, že vám přes závislosti doporučí aktualizovat polovinu distribuce, což nemusí být to, co chcete. Nedoporučuje se míchat stable a unstable, tyhle repozitáře jsou už od sebe hodně daleko. Nejčastější je naopak míchání testingu s unstable, případně experimental. To není plnohodnotná větev, jen doplňkový repositář k unstable. Pamatujte na to.

O prioritách

Abyste pochopili pinning, musíme se zastavit u systému priorit a popsat si ho detailně. Už jsme zmínili, že volbou výchozí (preferované) větve zvýšíme prioritu konkrétním balíčkům v oné větvi. To je nejjednodušší případ, ale máme mnohem více možností, jak prioritu ovlivňovat a tím měnit chování balíčkovacího systému.

Výchozí hodnoty priority jsou následující:

100
všechny nainstalované balíčky
500
nenainstalované balíky patřící do jiné než výchozí větve
990
nenainstalované balíky, které patří do výchozí větve

Pokud jsme tedy nastavili větve testing a unstable a jako výchozí jsme zvolili testing, pak všechny balíčky v testingu mají prioritu 990, kdežto balíčky v unstable mají prioritu 500 a proto nejsou při instalaci upřednostňovány. To můžeme dočasně změnit pomocí parametru  -t.

# aptitude -t unstable install nginx

Pokud tento příkaz spustíme, získají dočasně balíčky v unstable prioritu 990 a ty v testingu pak 500. Po ukončení příkazu se vše vrátí do původního stavu. Takto tedy můžeme nejjednodušším způsobem zamíchat novější balíčky z vyšší větve do stávajícího systému. Samozřejmě budou dodrženy i všechny požadované závislostí, zejména verze knihoven.

Poznámka: V příkladech používám Aptitude, protože je to v mnoha ohledech lepší a také doporučovaná varianta. Pokud jste ale stále zvyklí na apt-get a odmítáte ho opustit, vězte, že to bude fungovat stejně i s ním.

Pomocí pinningu ale budeme mít za chvíli možnost poměry změnit. K tomu ale bude potřeba o prioritách vědět ještě jednu věc. Platí logické pravidlo, že vyšší priorita přebíjí nižší prioritu, ale zároveň mají některé rozsahy hodnot speciální vliv na instalaci. Balíčkovací systém interpretuje priority takto:

méně než 0
lze jít i do záporných čísel, způsobí úplný zákaz instalace balíčku
0 až 99
nainstaluje balíček jen v případě, že žádná jiná verze nainstalovaná není
100 až 499
nainstaluje balíček, pokud neexistuje jeho novější verze v libovolném repozitáři
500 až 989
nainstaluje balíček, pokud neexistuje jeho novější verze ve výchozí větvi
990 až 999
nainstaluje balíček, i když pochází z jiné než výchozí větve
1000 a více
nainstaluje balíček, i kdyby to mělo znamenat snížení jeho verze (downgrade)

Výchozí větví míníme tu, kterou jsme zvolili dříve. Všimněte si, že žádná běžná priorita (100, 500 a 990) nedovoluje snižování verze balíčků (downgrade). Současné nastavení priorit pro jednotlivé repozitáře zjistíte pomocí výpisu příkazu:

$ apt-cache policy

Sledování větve

Z výše uvedeného plyne chování celého balíčkovacího systému, které ale nemusí být na první pohled úplně zřejmé. Zkusíme si popsat základní scénář. Řekněme, že jsme přidali repozitáře testing a unstable a jako výchozí jsme zvolili testing. Budeme chtít nainstalovat balíček, který je v obou větvích, ale má různé verze. Situace na začátku vypadá takto:

  • nainstalovaná: žádná
  • testing: 1.0
  • unstable: 2.0

Při klasickém aptitude install balíček se upřednostní balíček z testingu, protože má prioritu 990. Balíček z unstable se bude ignorovat – přestože je v novější verzi, má prioritu 500.

Pokud dočasně změníme výchozí repozitář příkazem aptitude -t unstable install balíček, priority větví se prohodí a balíčkovací systém upřednostní novější balíček z unstable a nainstaluje ho. Protože nemůže dojít k downgrade, systém si bude i do budoucna držet novější verzi z unstable.

Časem se může stát, že se v unstable objeví verze 2.1 a situace bude tedy vypadat takto:

  • nainstalovaná: 2.0
  • testing: 1.0
  • unstable: 2.1

Nejvyšší prioritu (990) bude mít samozřejmě verze 1.0, ale ta je nižší než v současnosti nainstalovaná verze 2.0 a bude se tedy ignorovat. Další nejvyšší prioritu (500) má nová verze 2.1 z unstable, která je navíc vyšší než současná nainstalovaná verze. Dojde tedy k aktualizaci.

Zapamatujte si, že systém tímto způsobem sleduje verzi balíčku z dočasně zvolené větve, dokud se ve výchozí větvi neobjeví stejná verze, jaká je právě nainstalovaná. K tomu dříve nebo později pravděpodobně dojde, když novější verze propadne z unstable do testingu. Řekněme, že se do unstable zároveň dostane ještě novější verze. Situace:

  • nainstalovaná: 2.1
  • testing: 2.1
  • unstable: 3.0

Protože nejnovější verze 3.0 má nižší prioritu (500) než verze v testingu (990), bude se systém nadále držet nainstalované verze a v budoucnu už bude sledovat jen novinky v testingu a novinky v unstable bude ignorovat. Přesně tak, jak tomu bylo na začátku.

Tři a víc repozitářů

Tohle funguje moc pěkně, pokud používáme dva repozitáře. Pokud ale nastavíme tři a více, situace se nám zkomplikuje. Repozitáře budou mít stejnou prioritu (kromě výchozího), a tak se nám může stát, že sice zvolíme ručně instalaci z některého z nich, ale při příští aktualizaci bude automaticky námi nainstalovaná verze balíčku přebita novější verzí z úplně jiného repozitáře.

  • nainstalovaná: 1.0
  • výchozí: 1.0
  • repo A: 2.0
  • repo B: 2.1 beta

Pokud jako výchozí dočasně zvolíme repozitář A, správně se nám nainstaluje verze 2.0. Jakmile ale necháme systém aktualizovat, budou mít repozitáře A i B shodně prioritu 500 a aktualizace nám nabídne novější verzi balíčku. To samozřejmě může být to, co chceme (ber odkudkoliv, ale chci to nejnovější), ale obvyklejší schéma je takové, že chceme většinu balíků z jednoho hlavního repozitáře (větve) a ostatní odjinud. Tady právě nastupuje pinning, který nám umožní věci detailně konfigurovat.

Pinning

Poznámka: Pokud chcete míchat repozitáře kvůli novější verzi některého z balíku pro stable, podívejte se nejdříve, jestli není v repozitáři backports. Tam se dostávají novější verze, kompilované pro stable. Pokud tam svůj balíček najdete a použijete, vyhnete se použitím backports řadě problémů, například příliš rozsáhlých aktualizací systému kvůli jednomu balíčku.

Pinning je obecný název pro ruční nastavení priorit jednotlivým balíčkům nebo celým repozitářům. Doslova si tak „připíchnete“ některý zdroj nad ostatní a on získá vyšší prioritu. Vše se provádí v adresáři /etc/apt/preferences.d/, ve kterém si můžete vytvářet konfigurační soubory. Ty se pak načítají podle abecedy.

Formát se skládá ze tří za sebou jdoucích řádků, za kterými následuje jeden řádek prázdný. Trojice vypadá vždy takto:

Package:
Pin:
Pin-Priority:

První položka určuje název balíčku a je možné v ní používat hvězdičku jako žolík. Snadno tak vybereme všechny balíčky nebo balíčky s podobným názvem. Nejčastější je volba všech balíčků v daném repozitáři, takže prostá hvězdička.

Pin specifikuje, odkud námi označovaný balíček pochází. Můžeme vybírat mezi verzí ( version), původem ( origin) nebo vydáním ( release). Verzi zvolíme jednoduše:

Package: nginx
Pin: version 1.2.3
Pin-Priority: 1001

Tím říkáme, že chceme konkrétní verzi, i kdyby na ni měl systém downgradovat. Druhou variantou je původ, kde volíme název serveru, na kterém leží repozitář.

Package: *
Pin: origin "ftp.mojerepo.cz"
Pin-Priority: 990

Nastavujeme prioritu pro všechny balíčky ve svém repozitáři tak, že budou mít stejnou váhu jako balíčky ve výchozí větvi. Rozhodovat pak bude jen vyšší verze toho kterého balíčku. Buď se nainstaluje z našeho FTP nebo z výchozího repozitáře.

Poslední variantou je vydání (release), kde je možné specifikovat konkrétní variantu balíčku. K tomu slouží další parametry, kterými je možné zvolit konkrétní archiv ( a=), jméno větve ( n=), verzi Debianu ( v=), oblast ( c=) a některé další méně podstatné (jsou popsané v man apt_preferences). Tyto položky je možné kombinovat, oddělte je čárkou. Například:

Package: *
Pin: release a=stable, c=main, v=7*
Pin-Priority: 1001

Poznámka: V mnoha položkách je možné využít hvězdičku. To se hodí, pokud chceme balíčky verze 1.2.3, ale zároveň neodmítáme opravné verze, které Debian označuje číslem za pomlčkou. Pokud tedy chceme verzi 1.2.3–1 a nebráníme se následující aktualizaci na 1.2.3–2, použijeme označení 1.2.3*.

bitcoin školení listopad 24

Tímto způsobem je možné si nastavit různé priority pro různé repozitáře, případně třeba zablokovat aktualizaci konkrétních balíčků. Můžeme docela dobře míchat různé repozitáře, různé balíčky i různé větve distribuce.

Při nesprávném použití pinningu se ovšem můžete dostat rychle do úzkých nebo můžete dostat systém do stavu, v jakém ho nechcete mít. Často už pak neexistuje cesta zpět, protože downgrade balíčků přináší mnoho problémů. Dávejte tedy vždy dobrý pozor na to, co vám vypisuje požadavek na aktualizaci a zda se s balíčky chystáte udělat přesně to, co jste zamýšleli.

Použité zdroje

Autor článku

Petr Krčmář pracuje jako šéfredaktor serveru Root.cz. Studoval počítače a média, takže je rozpolcen mezi dva obory. Snaží se dělat obojí, jak nejlépe umí.