A törlés nem egy triviális feladat, hiszen a csomagok fájljai szanaszét vannak szórva a fájlrendszer-hierarchiában. A leggyakoribb megoldás erre a problémára az, hogy minden egyes csomagra eltároljuk az általa telepített fájlok listáját. Ez a megoldás önmagában azonban közel sem teljes. Az első probléma mindjárt az, hogy nem minden telepített fájl egyforma. A közönséges fájloktól megkülönböztetünk konfigurációs fájlokat és úgy nevezett ghost fájlokat. A konfigurációs fájlok tárolják a program beállításait; ezeket a beállításokat egyfelől szeretnénk megőrizni a frissítések folyamán, másfelől az újabb verziók hozhatnak olyan változásokat, melyek a konfigurációs fájlokban további vagy más tartalmat kívánnak. Esetleg arra is szükség lehet, hogy egy program konfigurációs fájljait a csomag törlése után is megőrizzük. A ghost fájlok pedig olyan fájlok, melyek nem a telepítés során, hanem a program hasznaláta közben jönnek létre (pl. log fájlok), de ugyanúgy az adott programhoz tartoznak. A legtöbb elterjedt csomagkezelő nem támogatja a ghost fájlokat.
Azonban a helyzet még mindig nem ilyen egyszerű. Ugyanis egy csomagnak nem csak saját fájljai vannak, hanem gyakran a korrekt működéshez szükségesek bejegyzések más programok adatbázisaiban. Egy egyszerű példa az info fájlok esete, vagy bizonyos GNOME-os programoknál scrollkeeper használata, de ezek csak kiragadott példák. Ahhoz, hogy ezek a bejegyzések a törlések, telepítések és frissítések folyamán konzisztensek maradjanak, install szkriptekre van szükség.
A Gobo nevű disztribúció olyan megoldást talált ki, hogy kidobja a csudába a POSIX fájlrendszer-hierarchiát, és minden csomagot saját könyvtárba telepít. Ezzel látszólag leegyszerűsíti a törlést, sőt kéretlenül még a ghost fájlokat is jó eséllyel eltávolítja, viszont ez az alapötlet továbbra sem oldja meg a konfigurációs fájlok és a más programok bejegyzéseibe való belematatást. Nem vagyok Gobo szakértő, úgy hogy nem tudom van-e a Gobónak erre valami megoldása, de az „rm -rf”-fel való törlés és a törött szimbolikus linkek eltávolítása önmagában közel sem teljes. A másik hátránya a POSIX fájlrendszer-hierarchia felrúgásának az, hogy nincsenek többé szétválogatva a fájljaink konfigurációs fájlokra (/etc), valamint statikus (/usr) és változó (/var) adatokra. Ez pedig adna egy olyan rugalmasságot, hogy bizonyos részeket (pl. /usr) lehet több rendszer (akár több gép) között közösen tárolni, vagy az egyes részeket ezekből külön partícióra telepíteni, s a többi. A készítők azzal érvelnek, ezek a lehetőségek jók voltak a UNIX hőskorában a nagygépeken, de a mai desktop rendszereken feleslegesek. Valamilyen szinten igazuk van, csak hát ezzel éppen hogy kizárják a Gobót azokról a helyekről, ahol ezek a lehetőségek tényleg hasznosak.
Mindez idáig csak egyetlen (lefordított) csomag tulajdonságairól volt szó. Egy csomagnak szüksége lehet bizonyos más csomagokra. Van, hogy bizonyos más csomagok nélkül egyáltalán nem funkcionál az adott program; van, hogy más csomagok kellenek az adott program bizonyos extrafunkcióinak működéséhez; és olyan is van, hogy bizonyos más csomagok olyan funkciókkal bővítik a programot, amely abban a csomagban eredetileg sem volt megtalálható. Ugyanakkor olyan is előfordul, hogy két csomag ütközik egymással, vagy az egyik csomag helyettesítheti a másikat, ellátja a másik funkcióját.
Az a tény, hogy egy program opcionális függőségeinek megválasztásától függően más és más lehet az adott program csomagfüggőséglistája, érdekes döntésre készteti a disztribúciókészítőket. A disztribútorok szeretik az összes elérhető funkciót beleforgatni a csomagokba, hátha valakinek szüksége lesz rá. Nézzünk egy példát: „Tekintsük az A csomagot. Az A csomag működéséhez elengedhetetlen a libB.so dinamikus könyvtár, valamint a b1 és b2 binárisok. Ez a két bináris és a library a B csomag része. A B csomag tartalmaz további binárisokat: b3, b4, b5, b6. Ezek közül a b3 és a b4 függősége a libK.so könyvtár, amely a K csomag része. Tehát az A csomag működéséhez egyáltalán nincs szükség a K csomaghoz, viszont ha megkérjük a csomagkezelőt, hogy telepítse az A csomagot, a függőséget értelmében a K csomagot is telepíteni fogja. Gyakran fölösleges függőségi hálózat tovább is folytatható, ami tetemes mennyiségű felesleges csomag telepítését okozza.” Nézzük, milyen megoldások születtek ezekre a problémákra:
- Forrás alapú disztribúciók gyakorlatilag eliminálják a problémát azzal, hogy a felhasználóra bízzák, hogy milyen opcionális függőségeket telepítenek és engedélyeznek a fordítás során.
- „Don't bother!” Ennek két változata lehet:
- Ami fel van telepítve, de nem használom, az nem lassítja a gép futását, csak fogja a helyet a merevlemezen és ugyanúgy frissíteni kell, mint a hasznos dolgokat. A merevlemez olcsó, sávszélesség van elég, nem zavartatom magam apróságokon.
- A csomagkezelő nem kényszeríti ki a függőségek teljesülését (pl. Slackware). Tehát itt megkérjük a csomagkezelőt, hogy tegye fel az A és a B csomagokat, a B csomag egyes részei nem fognak működni a K csomag hiánya miatt, de azok a részek számunkra úgyis fölöslegesek, ezért nem zavartatjuk magunkat rajta.
- Daraboljuk fel a csomagokat (pl. Debian), és a függőségek vonatkozzanak csak a szükséges darabokra! Itt az A-nak függősége lesz a libB és a B-core, a b3, b4, b5, b6 binárisok pedig a B csomagban lesznek, és a B-nek lesz függősége a libB, B-core, valamint a K. Vagy egy másik példa: Az Amarokba beleforgatjuk a MySQL támogatást. Ekkor az Amarok nem fog működni a libmysqlclient.so nélkül. Ha nincs szükségünk MySQL támogatásra, akkor elegendő feltelepíteni egy pár száz kilobájtos libmysqlclient csomagot, nincs szükség teljes MySQL-re. Ha azonban szeretnénk, hogy az Amarok MySQL adatbázisban tárolja a zenegyűjteményünk információit, akkor egyszerűen feltelepítjük a MySQL szervert, az Amarokot nem kell újra forgatni, mert már benne van a MySQL támogatás.
Eddig a kész csomagokat és az ezeket kezelő csomagkezelő tulajdonságairól és megközelítéseiről esett szó. Most áttérünk a csomagkészítés problémáinak tárgyalására. Az alapvető megoldás a csomagkészítésre, hogy egy csomagot egy könyvtárba telepítünk, mintha az lenne a gyökérkönyvtár, aztán becsomagoljuk, és meg is vagyunk vele. Ez általában a make DESTDIR=ide_pakold install paranccsal történik. Persze, valójában ez nem elég mindenre. Van még két dolog, ami fontos, de még eddig nem említettem. Az egyik a debug információk eltávolítása a binárisokból és a library-kből. Ez nem csak a merevlemezen elfoglalt helyet csökkenti, hanem a memóriában elfoglalt helyet és a betöltődési időt is, e két dolgot pedig igencsak kívánatos csökkenteni. A másik a man és info fájlok tömörítése. Ez tisztán csak a helyfoglalás miatt számít, mivel a szövegek jól tömöríthetőek, és nagy részüket csak ritkán vagy soha nem olvassuk. Ezeken kívül még el kell rendezni azokat a dolgokat, amelyek a bináris csomagkezelésnél már tárgyaltam: a konfigurációs (és esetlegesen a ghost) fájlok meghatározása, install szkriptek elkészítése, függőségek és konfliktusok megírása.
Ha egy egyszerű csomagkezelővel kezdünk el csomagokat készíteni (pl. SlackBuild-et írunk), számos mechanikusan ismétlődő, unalmas dolog fog ismétlő a csomagok nagy részében: debug információk stripelése, man és info fájlok tömörítése, install szkriptbe megírni az info fájlok regisztrációját, esetlegesen hibás fájljogosultságok javítása, scrollkeeper bejegyzések meghívása, Perl modulok regisztrálása, stb. Ezek jól automatizálhatóak, ahogyan pl. a Debian debhelper szkriptjei segítik a .deb csomagok készítését. Elegendő meghívni a dh_fixperms, dh_compressman, dh_installinfo, dh_perlmodules és hasonló nevű szkripteket, és ha szükséges, akkor ezek még az install szkriptekbe is beírják a szükséges bejegyzéseket.
Más feladatokat pedig, mint például a helyes függőségek összeírását, nem triviális megoldani. Debiannál pl. a dh_shlibdepends az ldd parancs segítségével felderíti, hogy milyen dinamikus könyvtárakhoz kötődnek a csomagban található binárisok és library-k, megállapítja, hogy ezek melyik csomaghoz tartoznak, és ezeket a csomagot hozzáadja a függőségek listájához. Többek által alkalmazott ötlet a függőségek ellenőrzésére a chrootban történő buildelés, ugyanis ekkor csak bizonyos csomagok állnak rendelkezésre, és sikeres build és működés esetén ennek részhalmaza lehet csak a függőségek halmaza.
Megjegyzés: A dh_* szkriptek neveire már nem emlékszem teljesen, lehet, hogy nem pontosan így hívják őket, de valami hasonló nevük van.
Egy profi csomagolónak annál könnyeb dolga van, minél több az automatizáció. Egy kezdő viszont könnyeben ér el (gyakran kétes) eredményt egy egyszerűbb csomagkészítő mechanizmus használatával.
Kiegészítés:
Köszönöm a kiegészítéseket. A cikk ihletője ez a hozzászólás volt. Tulajdonképpen azt szerettem volna bemutatni, hogy a csomagkészítés egy összetett dolog. Ez az összetettség mindig megmarad, akárhogyan tologatjuk:
- Lehet, hogy a maga csomagkészítő és a használata is nagyon egyszerű, viszont ebben az esetben rosszul látja el a funkcióját.
- Lehet, hogy könnyű elkészíteni a csomagot, viszont egy bonyolult automatizáció van mellette, és a felhasználónak fogalma sincs, hogy az hogy működik.
- Vagy pedig ismeri, és átlátja az a bonyolult rendszert, ez a legszerencsésebb a csomagkészítés teljesítményét illetően, viszont ehhez kell a legtöbb tudás.
- Lehet, hogy a csomagkészítő egyszerű, könnyű átlátni pontosan mit csinál, csak sokat kell mindig kézzel barkácsolni.
Ha biztosak akarunk lenni benne, hogy pontosan mit csináltunk, és hogy az korrekt volt, akkor az utóbbi két lehetőség közül választhatunk. Ha bonyolult a rendszer (sok az automatizáció), akkor sok tanulás kell, hogy megelőzze a csomagkészítést. Ha pedig egyszerű a rendszer, akkor sok a kézimunka.
- utpKabel blogja
- A hozzászóláshoz be kell jelentkezni
- 2020 megtekintés
Hozzászólások
Van egy harmadik fele megkozelites is.
Bizonyos tipusu csomagok eseteben altalanossagban elmondhato, hogy X modon kell mindegyiket telepiteni, es meg a helper scriptek meghivasa is csak felesleges idopocsekolas a csomagkeszites soran. Ezen felul vannak bizonyos dolgok, amik a legtobb csomag eseteben ugyanugy mennek _mindig_, es erdemes lehet oket automatizalni, hogy csak a tenyleg fontos dolgokra kelljen koncentralni.
Vegyunk egy konkret peldat, Gentoo es mondjuk egy alap csomag telepitese, mondjuk euses.
1) Az euses egy autoconf rendszert hasznalo cucc, kovetkezeskepp a forditasa "./configure && make && make DESTDIR=${D} install" metodussal megy
2) van neki man oldala
3) van neki binarisa
Gentoo eseteben van lehetoseg (foleg most az EAPI 2 miatt) egy alap automatizalasra:
1) az econf script automatikusan lefut a --prefix=/usr --sysconfdir=/etc --mandir=/usr/share --libdir=/usr/lib ... parameterekkel ha letezik egy futtathato configure nevu script, es nincs explicite megadva semmi.
2) Ezutan ellenorzes tortenik a Makefile altalanos elnevezeseire (amit a GNU make elkezel) es kiadasra kerul egy make parancs, ha van talalat
3) Ujabban mar a make install is automatikus ha fenn allnak a 2) pontban levo feltetelek, es nem halt ki a csomagscript.
Miutan az al-telepites fazisa vegetert, elkezdodik az utolagos ellenorzes:
1) a binarisok utan a scanelf kutat, amit talal, az - ellenorzes utan - atadasra kerul a strip -nek
2) man, doc es info fajlok utan szinten automata kutatas tortenik, ha esetleg a make install nem a rendszer csomagolojaval telepitette volna, akkor automata ujracsomagolas tortenik
3) a konfig fajlokkal halistennek nincs gond, a CONFIG_PROTECT kornyezeti valtozo szabalyozza ezt dinamikusan.
4) a csomagok tehetnek akar kulonfele utvonalakra is futtathato dolgokat, vagy manualokat, ilyenkor egy custon environment fajlt kell telepitenie az illeto csomagnak, es a telepites utan rogton ujra kiertekelodnek a kornyezeti valtozok, csak fel kell nyalatni a /etc/profile fajlt ujra.
5) a bejegyzesek (scrollkeeper, satobbi) altalaba rendelkeznek egy rebuild eszkozzel, es nem is tart olyan soka az adatbazis ujraepitese.
Persze, van egy bizonyos sema, amibe belekenyszerit, de ez a legtobb rendszer eseteben igy van. Viszont, ha rajossz, hogy hogyan lehet a gepies munkakat a csomagkezelore bizni, ahelyett, hogy explicite te adogatnad meg (es esetleg kevesbe optimalisan), akkor a sajat eleted valik konnyebbe.
Gentoo eseteben az automatizacio kezd olyan mereteket olteni, hogy egy .ebuild kiterjesztesu fajlt meg touch-olva a csomagkezelo kitolti a hianyzo infokat (meg nem tartunk itt, de latok ra eselyeket). Ez meg mar egy kezdonek is pofonegyszeru.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Köszönöm a kiegészítést. Csak azt nem értem, hogy ha ez a harmadik megközelítés, akkor melyik volt az első kettő?
- A hozzászóláshoz be kell jelentkezni
Te soroltál fel hármat, szerintem elírta, ő egy negyedik féle megközelítésre gondolt. :)
Amúgy klassz írás, tetszik hogy nem konkrétan adott rendszer csomagkezelőjének hátteréről írsz, hanem általános csomagkészítési, -kezelési gondolatokról.
Automatizációhoz és konfig fájlokhoz kis gondolat. Vannak ugye, akik verziókezelő rendszert használnak /etc könyvtárhoz, sajnos ez kézi dolog vagy apt-get/aptitude lefutása után indítják el a commitolást automatikusan, de ez se az igazi. Talán lesz 1x egy jól használható verziókezelő fájlrendszer, amire kerülhetne az etc.
- A hozzászóláshoz be kell jelentkezni
Szerintem érdemes lenne megnézned az UHU-Linux csomagkészítő rendszerét:
http://wiki.uhulinux.hu/index.php/UHU-Linux:Csomagk%C3%A9sz%C3%ADt%C3%A…
http://wiki.lme.hu/lmewiki/index.php/UHU_csomagk%C3%A9sz%C3%ADt%C3%A9s_…
http://wiki.uhulinux.hu/index.php/UHUBUILD_0.2.245
-----
"Egy jó kapcsolatban a társunkat az ő dolgában kell támogatni, nem a miénkben."
- A hozzászóláshoz be kell jelentkezni