Animace

HomeO mněBlogKontaktVěže...Přihlásit

Kompilovaný update systému

Datum:

2008-03-17

Čas:

20:54:48

Zobrazení:

2060

Reakcí:

0

Uživatel:

andrej

Kategorie:

Software, informatika

Představte si, že máte ArchLinux. (To je pro (nedobrovolné) uživatele průjmů firmy Microsoft jistě krásná představa...) Řeknete si, že když už můžete bez námahy klidně pětkrát denně aktualizovat veškerý software na svém počítači, možná by bylo dobré se zamyslet i nad jeho optimalizací. Binární balíčky jsou totiž v případě platformy Intel zkompilované tak, že zpětná kompatibilita sahá až po Pentium II. Dnes ale většinou máte Pentium M, Pentium 4, Pentium XyZfPlBmPtV, Core Duo nebo Core 2 Duo. Uživatelé rozumných operačních systémů právem očekávají maximální využití všech vlastností svého hardware. Co s tím? To je první podstatná otázka.

Druhá podstatná otázka jde v této úvaze ještě dál: Dobře, chci kompilovaný update. Ale co když mám víc než jeden procesor? Nedala by se kompilace nějak zrychlit? Jak se ukáže, na obě otázky lze při troše snahy najít kladnou odpověď. Uživatelé ArchLinuxu si už jistě všimli, že ke správci balíčků pacman existuje alternativa srcpac, který dělá přesně totéž, až na rozšiřující option -b. Ten zajistí, že se místo stahování balíčku v binární podobě spustí kompilace pomocí makepkg. Jenže má to háček: Protože Arch Build System (i samotný pacman) prošel v posledních měsících velmi rychlým vývojem, srcpac s ním přestal být kompatibilní. Jde především o to, že vývojáři konečně pochopili nepříjemné bezpečnostní riziko, které spočívalo v používání ABS pod rootem, a zjednali nápravu. Naneštěstí zatím nikdo neupravil srcpac tak, aby byl s tímto novým přístupem kompatibilní, a ten se tak stal zcela nepoužitelným. (Navíc musím konstaovat, že i v době, kdy byl považován za funkční, obsahoval tolik chyb, že bylo lépe se mu vyhnout.)

Neodpustím si ještě jednu drobnou úvahu na téma bezpečnosti ABS. Přiznejme si, že zavedení konvence „nespouštět ABS pod rootem“ je bez dalších změn tak trochu skokem z nádrže chemického WC do louže... Jistě, je tu bezesporu zlepšení v tom smyslu, že systém nemůže být poškozen vadným PKGBUILDem, vadným obsahem repository a podobnými nástrahami. Ale jak jsou chráněna data uživatele, který kompilaci přes ABS provádí? Jistě, někdo může argumentovat tím, že strom ABS prochází důkladným auditem a nemělo by v něm být nic závadného. Ale jak nás učí historie operačních systémů, ochrana musí být zajištěna tak, aby selhání nebylo technicky možné. Žádné lidské záruky jednoduše nestačí. Podle mého názoru by tedy měl existovat speciální uživatelský účet bez možnosti přihlášení, který by byl vyhrazený pro kompilaci balíčků. Tento účet by neměl přístup jednoduše nikam s výjimkou stromu /var/abs a vhodného adresáře pro uložení výsledných souborů. Pak by se makepkg spouštěl pod rootem, jako tomu bylo dříve, a později by svou relaci přepnul do režimu zmíněného omezeného uživatele. (Toto je standardní a korektní řešení, které používá drtivá většina dnešních unixových démonů.)

Zpět k tématu: Řekněme, že nechcete použít standardní, prověřený a bezpečně funkční způsob aktualizace systému a chcete se vydat vlastní cestou. Tedy dobře, činíte tak na vlastní nebezpečí. Prvním krokem je správné nastavení /etc/abs/abs.conf a /etc/makepkg.conf. Pak už stačí jen mít vhodný skript pro kompilovaný update. Idea tkví jednoduše v tom, že zjistíme, u kterých balíčků v repository se změnilo číslo verze, a necháme je zkompilovat (včetně případných závislostí) standardním postupem pomocí makepkg.

Pokud máme jen jeden procesor, nic dalšího už nevymyslíme. Stačí jen výše zmíněný nápad popsat skriptem:

#!/bin/bash

su -c 'pacman -Sy; abs; chgrp -R users /var/abs; chmod -R g+rwX /var/abs;' || exit 1

TO_UPDATE=`{ pacman -Q; echo ---; pacman -Sl | cut -d' ' -f2,3; } | \
awk '
BEGIN { ORS = " "; }
/^---$/ { all = 1; }
{
        if ( all ) {
                command = "vercmp " installedArray[ $1 ] " " $2;
                command | getline compared;
                close( command );
                if ( compared < 0 ) print $1;
        } else {
                installedArray[ $1 ] = $2;
        }
}'`

echo $TO_UPDATE | tr ' ' "\n"

cd /var/abs
for NAME in $TO_UPDATE; do
        ( cd `find -name "$NAME"`; makepkg -bc )
done

Dva procesory činí celou situaci zajímavější. Možná by se dalo použít složitější řešení na bázi distcc, ale zde se spokojíme pouze s jednoduchým skriptem. Granularita celé úlohy je pak sice mnohem hrubší, ale zrychlení i přesto bude stát za to. Samozřejmě může nastat nepříjemný případ, kdy se aktualizuje spousta drobných balíčků a jeden obrovský. Je však dobré si uvědomit, že kompilátor sestává přinejmenším z tří nezávislých procesů, nemluvě o vláknech. Není tedy pravda, že by v nejhorším případě jeden procesor zcela zahálel. Pouze nebude plně vytížen. Zde je skript pro dvouprocesor:

#!/bin/bash

su -c 'pacman -Sy; abs; chgrp -R users /var/abs; chmod -R g+rwX /var/abs;' || exit 1

TO_UPDATE=`{ pacman -Q; echo ---; pacman -Sl | cut -d' ' -f2,3; } | \
awk '
BEGIN { ORS = " "; }
/^---$/ { all = 1; }
{
        if ( all ) {
                command = "vercmp " installedArray[ $1 ] " " $2;
                command | getline compared;
                close( command );
                if ( compared < 0 ) print $1;
        } else {
                installedArray[ $1 ] = $2;
        }
}'`

echo $TO_UPDATE | tr ' ' "\n"

mkdir /tmp/ArchLinuxUpdate
P1=/tmp/ArchLinuxUpdate/process1
P2=/tmp/ArchLinuxUpdate/process2

cd /var/abs
echo -n 0 > $P1
echo -n 0 > $P2

for NAME in $TO_UPDATE; do
        GETNEXT=
        until [ $GETNEXT ]; do
                if [ `cat $P1` -eq 0 ]; then
                        echo -n 1 > $P1
                        ( cd `find -name "$NAME"`; makepkg -bc; echo -n 0 > $P1; ) &
                        GETNEXT=true
                elif [ `cat $P2` -eq 0 ]; then
                        echo -n 1 > $P2
                        ( cd `find -name "$NAME"`; makepkg -bc; echo -n 0 > $P2; ) &
                        GETNEXT=true
                else
                        sleep 1
                fi
        done
done
while [ `cat $P1` -eq 1 -o `cat $P2` -eq 1 ]; do sleep 1; done

rm -R /tmp/ArchLinuxUpdate

Jak si pozorný čtenář jistě všiml, balíčky nejsou rovnou instalovány. Pouze se zapíší do cílového adresáře. Tento postup je sice bezpečnější, ale v případě, kdy je potřeba rekurzivně aktualizovat závislosti balíčku, může být trochu na obtíž. Je věcí uživatele, jak se rozhodne. Pro všechny případy ještě jednou připomínám, že je nutné správně nastavit /etc/makepkg.conf, zejména optiony kompilátoru. Jinak kompilované aktualizace ztrácejí smysl.

Rád bych upozornil též na dvě podstatné nevýhody tohoto postupu. První z nich tkví v tom, že některé balíčky v ArchLinuxu doslova „visí ve vzduchu“. To znamená, že v binární repository sice jsou, ale jim odpovídající PKGBUILD je zjevně chybný nebo zastaralý. Přestože jsou takové případy relativně vzácné, pořád ještě mohou nastat. (Obávám se, že správce balíčku nemá povinnost udržovat PKGBUILD a balíček v repository ve vzájemném souladu.) Druhá nevýhoda spočívá v tom, že změny mohou být mnohem složitější než pouze nahrazení balíčku novější verzí. Občas dochází ke slučování balíčků, složitějším reorganizacím, změnám názvu a podobně. Uvedené skripty pochopitelně nic z toho neřeší a o balíčky, kterých se to týká, se musí uživatel postarat sám.

Občas se hodí uklidit nepořádek, který správce balíčků i příkaz makepkg po sobě nechávají. Toho se docílí například příkazy pacman -Scc, makepkg -C, rm /X/*, rm /Y/*, cd /var/abs && rm -R *. Stačí dosadit za X adresář, kam makepkg zapisuje vytvořené balíčky a za Y adresář, kam ukládá stažené zdrojové soubory. V mém případě jde o adresáře /home/pkg a /home/src, ale každý si to jistě v /etc/makepkg.conf nastaví po svém. Adresářový strom ve /var/abs se automaticky aktualizuje z CVS repository a lze ho tedy bez následků celý smazat, ať už za účelem uvolnění místa na disku nebo pro dobrý pocit z vzorného pořádku. :-)

Odpovědět

| Platné XHTML a CSS| | Prohlížeč: Gecko (Firefox), KHTML (Konqueror) | | Počítadla: 284421 zobrazení, 16624 IP adres |