FreeBSD kézikönyv
Előző | Fejezet 24. A FreeBSD frissítése és frissen tartása | Következő

# 24.7. Az alaprendszer újrafordítása

Miután sikerült a helyi forrásfánkat a FreeBSD egy nekünk szimpatikus (FreeBSD-STABLE, FreeBSD-CURRENT és így tovább) változatához igazítanunk, elérkezett az idő, hogy a segítségével újrafordítsuk az egész rendszert.

> Készítsünk biztonsági mentést: Nem tudjuk eléggé nyomatékosítani, hogy mielőtt nekikezdenénk, készítsünk egy biztonsági mentést a rendszerünkről. Míg az alaprendszer újrafordítása nem túlságosan bonyolult feladat (egészen addig, amíg a megadott utasításokat követjük), saját magunk vagy mások hibájából fakadóan kialakulhatnak olyan helyzetek, amikor a rendszer nem lesz képes elindulni.

> Mindenképpen győzödjünk meg róla, hogy tisztességesen elvégeztük a mentést és akad a kezünk ügyében egy javításra felhasználható rendszerindító floppy vagy CD. Valószínűleg soha nem lesz ténylegesen szükségünk rájuk, azonban jobb félni, mint megijedni!

> Iratkozzunk fel a megfelelő levelezési listákra: A FreeBSD-STABLE és FreeBSD-CURRENT ágak természetüknél fogva fejlesztés alatt állnak. A FreeBSD fejlesztését is emberek végzik, ezért előfordulhatnak benne tévedések.

> Ezek a tévedések gyakran csak ártalmatlan apróságok, amelyek hatására kapunk például egy ismeretlen diagnosztikai hibát. De ezzel szemben létrejöhetnek pusztító erejű hibák is, amelyek hatására a rendszerünk nem lesz képes elindulni, károsodnak az állományrendszerek (vagy még rosszabb).

> Ha ilyen történik, akkor egy “felszólítást” (egy “heads up” témájú üzenetet) küldenek az érintett változatokhoz tartozó listákra, amelyben igyekeznek kifejteni a probléma természetét és a rendszerre mért hatását. Miután “minden rendbejött”, a probléma megoldásáról is küldenek egy értesítést.

> Ha a FreeBSD-STABLE levelezési lista vagy a FreeBSD-CURRENT levelezési lista olvasása nélkül próbáljuk meg használni a FreeBSD-STABLE és FreeBSD-CURRENT verziókat, akkor csak magunknak keressük a bajt.

> Ne használjuk a `make world` parancsot: Rengeteg régebben készült dokumentáció erre a feladatra a `make world` parancs kiadását javasolja. Ennek használatával azonban átlépünk olyan fontos lépéseket, amelyek valójában csak akkor lennének kihagyhatóak, ha pontosan tudjuk mit csinálunk. Ezért az esetek döntő többségében nem a `make world` használatára van szükségünk, hanem a most bemutatandó eljárásra.

## 24.7.1. A rendszer frissítése dióhéjban

A frissítés megkezdése előtt érdemes elolvasnunk a `/usr/src/UPDATING` állományt, ahol a letöltött források használatához elvégzendő előzetes intézkedésekről kaphatunk hírt. Ezután kövessük az alábbiakban körvonalazott módszer egyes lépéseit.

Ezek a lépések feltételezik, hogy egy korábbi FreeBSD verziót használunk, tehát a fordító, a rendszermag, az alaprendszer és a konfigurációs állományok valamelyik régebbi változatát. Alaprendszer alatt, amelyet sokszor csak a “world” néven hivatkozunk, a rendszer számára alapvető fontosságú binárisokat, programkönyvtárakat és programfejlesztéshez szükséges egyéb állományokat értjük. Maga a fordítóprogram is része ennek, azonban tartalmaz néhány speciális megszorítást.

Mindezek mellett továbbá feltételezzük, hogy előzetesen már valamilyen módon letöltöttük a friss forrásokat. Ha rendszerünkön ezt még nem tettük volna meg, akkor a 24.6 Szakasz segítségével tájékozódhatunk részletesen arról, hogyan tölthetjük le a legfrissebb verziót.

A rendszer forráskódon keresztüli frissítése egy kicsivel körülményesebb, mint amennyire elsőre látszik. A FreeBSD fejlesztők az évek során fontosnak találták, hogy a folyamatosan felszínre bukkanó, elkerülhetetlen függőségek tükrében meglehetősen drámai módon megváltoztassák az erre javasolt módszert. Ezért a szakasz további részében a pillanatnyilag javasolt frissítési megoldás nyomán fogunk haladni.

A sikeres frissítések során az alábbi akadályokkal kell mindenképpen szembenéznünk:

- A fordító régebbi változata nem feltétlenül lesz képes lefordítani az új rendszermagot. (Illetve a régebbi fordítóprogramok tartalmazhatnak hibákat.) Ezért az új rendszermagot már a fordító új változatával kell előállítanunk. Ebből következik, hogy az új rendszermag elkészítéséhez először a fordítóprogram újabb változatát kell lefordítanunk. Ez viszont nem feltétlenül jelenti azt, hogy az új rendszermag fordítása előtt az új fordítóprogramot telepítenünk is kellene.

- Az új alaprendszer esetenként bizonyos új funkciókat igényelhet a rendszermagtól. Ezért a frissebb alaprendszer telepítése előtt telepítenünk kell a frissebb rendszermagot.

- Ez az előbb említett két akadály képzi az okát a következő bekezdésekben bemutatott `buildworld`, `buildkernel`, `installkernel`, `installworld` sorozatnak. Természetesen léteznek további egyéb indokok is, amiért még érdemes az itt leírtak szerint frissíteni a rendszerünket. Ezek közül most vegyünk néhány kevésbé nyilvánvalóbbat:

  - A régebbi alaprendszer nem minden esetben fog problémamentesen együttműködni az új rendszermaggal, ezért az alaprendszer újabb változatát szinte azonnal az új rendszermagot követően kell telepítenünk.

  - Vannak olyan konfigurációs változtatások, amelyeket még az új alaprendszer telepítése előtt el kell végeznünk, a többi viszont veszélyes lehet a korábbi alaprendszerre. Ezért a konfigurációs állományokat általában két külön lépésben kell frissíteni.

  - A frissítés során nagyrészt csak állományok cserélődnek el és újabbak érkeznek, a korábbiak nem törlődnek. Ez bizonyos esetekben azonban gondokat okozhat. Ennek eredményeképpen a frissítés során időnként előfordulhat, hogy magunknak kell manuálisan némely megadott állományokat törölnünk. Elképzelhető, hogy ezt a jövőben még majd automatizálni fogják.

  Ezek a megfontolások vezettek tehát az ismertetendő eljárás kialakításához. Ettől függetlenül adódhatnak olyan helyzetek, amikor további lépéseket is be kell iktatnunk, viszont az itt bemutatott folyamat egy ideje már viszonylag elfogadottnak tekinthető:

  1. `make buildworld`

     Először lefordítja az új fordítóprogramot és néhány hozzá tartozó eszközt, majd ennek felhasználásával elkészíti az alaprendszer többi részét. Az eredmény a `/usr/obj` könyvtárban keletkezik.

  2. `make buildkernel`

     Eltérően a config(8) és make(1) programok korábban javasolt alkalmazásától, ezzel a paranccsal már a `/usr/obj` könyvtárban létrehozott új fordítót használjuk. Ez védelmet nyújt a fordító és rendszermag változatai közti eltérésekből fakadó problémák ellen.

  3. `make installkernel`

     Telepíti a lemezre az új rendszermagot és a hozzá tartozó modulokat, ezáltal lehetővé válik a frissített rendszermag betöltése.

  4. Átváltás egyfelhasználós módba.

     Egyfelhasználós módban a minimálisra csökkenthetjük a futó szoftverek frissítéséből adódó bonyodalmakat. Ezzel együtt minimálissá válik a régi alaprendszer és az új rendszermag eltéréseiből eredő problémák előfordulása is.

  5. `mergemaster -p`

     Az új alaprendszer telepítéséhez elvégzi a konfigurációs állományok részéről szükséges frissítéseket. Például felvesz még nem létező csoportokat vagy felhasználókat. Ez gyakran elengedhetetlennek bizonyulhat, mivel ha a rendszer legutóbbi frissítése óta újabb csoportok vagy felhasználók kerültek be az alaprendszerbe, a `installworld` csak akkor tud hibamentesen lefutni, ha ezek már a futásakor is elérhetőek.

  6. `make installworld`

     Átmásolja a `/usr/obj` könyvtárból a korábban elkészített új alaprendszert. Lefutása után már mind az új rendszermag és az új alaprendszer a megfelelő helyén található.

  7. `mergemaster`

     Feldolgozzuk a korábbi fázisból fennmaradó konfigurációs állományok frissítését, mivel most már elérhető az új alaprendszer.

  8. A rendszer újraindítása.

     Az új rendszermag és az új konfigurációs állományokkal futó alaprendszer használatához teljesen újra kell indítanunk a számítógépünket.

  Ha a FreeBSD ugyanazon fejlesztési ágán belül frissítjük a rendszerünket, például a 7.0 kiadásról a 7.1 kiadásra, akkor értelemszerűen nem kell az iménti eljárás minden lépését szorosan követni, hiszen nagyon valószínűtlen, hogy komoly eltérések lennének a fordítóprogram, a rendszermag, az alaprendszer és a konfigurációs állományok között. Ilyenkor akár nyugodtan kiadhatjuk a `make world` parancsot, majd kérhetjük a rendszermag fordítását és telepítését.

  A fejlesztési ágak közti váltás során azonban könnyen érhetnek minket meglepetések, ha nem a megadottak szerint járunk el.

  Egyes váltásokhoz (például 4.`X` és 5.0 között) további lépések megtétele is szükséges lehet (például adott állományok törlése vagy átnevezése még az `installworld` előtt). Ilyenkor mindig figyelmesen olvassuk át a `/usr/src/UPDATING` állományt, különös tekintettel a végére, mivel gyakran ott adják meg a konkrét verzióváltáshoz szükséges teendőket.

  A szakaszban összefoglalt lépések egyfajta evolúciós folyamat eredményei, melynek során a fejlesztők felismerték, hogy nem tökéletesen kivédeni az összes frissítéssel járó problémát. A javasolt eljárás remélhetőleg viszont még sokáig érvényes marad.

  > Megjegyzés: A FreeBSD 3.`X` vagy annál is korábbi változatok frissítése még ennél is több ügyességet kíván. Ha ilyen verziót akarunk frissíteni, akkor feltétlenül olvassuk el az `UPDATING` állományt!

  Röviden tehát a FreeBSD forráskódon keresztüli frissítését így foglalhatjuk össze:

    # cd /usr/src
    # make buildworld
    # make buildkernel
    # make installkernel
    # shutdown -r now

> Megjegyzés: Néhány ritka esetben a `buildworld` lépés előtt szükségünk lehet a `mergemaster -p` parancs lefuttatására is. Erről az `UPDATING` állományból tudakozódhatunk. Általában azonban nyugodt szívvel kihagyhatjuk ezt a lépést, kivéve, ha nem egy vagy több főbb FreeBSD változatot átívelő frissítést végzünk.

Miután az `installkernel` sikeresen befejezte a munkáját, indítsuk újra a számítógépet egyfelhasználós módban (a betöltő parancssorában adjuk ki `boot -s` parancsot). Itt futtassuk a következőket:

    # adjkerntz -i
    # mount -a -t ufs
    # mergemaster -p
    # cd /usr/src
    # make installworld
    # mergemaster
    # reboot

> Olvassuk el a magyarázatokat: Az iménti leírt folyamat csupán rövid összefoglalás, amivel némi gyorstalpalást igyekeztünk adni. Az egyes lépések megértéséhez azonban javasolt átolvasni a most következő szakaszokat is, különösen abban az esetben, ha saját rendszermagot akarunk használni.

## 24.7.2. Nézzük meg a `/usr/src/UPDATING` állományt

Mielőtt bármihez is nekifognánk, keressük meg a `/usr/src/UPDATING` (vagy hasonló, a forráskód másolatunk tényleges helyétől függő) állományt. Ebben adják hírül az esetlegesen felmerülő problémákra vonatkozó fontosabb információkat, vagy határozzák meg az egyes lefuttatandó parancsok pontos sorrendjét. Amennyiben az `UPDATING` ellentmondana az itt olvasottaknak, az `UPDATING` tartalma a mérvadó.

> Fontos: A korábban tárgyaltak szerint az `UPDATING` elolvasása nem helyettesíti a megfelelő levelezési listák figyelemmel kísérését. Ez a két elvárás nem kizárja, hanem kiegészíti egymást.

## 24.7.3. Ellenőrizzük az `/etc/make.conf` állományt

Vizsgáljuk át a `/usr/share/examples/etc/make.conf` és az `/etc/make.conf` állományokat. Az előbbi tartalmaz néhány alapértelmezett beállítást - ezek javarészét megjegyzésbe rakták. Ha használni akarjuk a rendszer lefordítása során, tegyük bele ezeket az `/etc/make.conf` állományba. Ne felejtsük el azonban, hogy minden, amit megadunk az `/etc/make.conf` állományba, a `make` minden egyes elindításakor felhasználásra kerül. Éppen ezért olyanokat érdemes itt beállítani, amik az egész rendszerünket érintik.

A legtöbb felhasználó számára az `/etc/make.conf` állományhoz a `/usr/share/examples/etc/make.conf` állományban található `CFLAGS` és `NO_PROFILE` sorokra lesz szüksége, melyeket kivehetünk a megjegyzésből.

A többi definíció (`COPTFLAGS`, `NOPORTDOCS` és így tovább) használatáról már mindenki maga dönt.

## 24.7.4. Frissítsük az `/etc` tartalmát

Az `/etc` könyvtár tartalmazza a rendszer beállításaival kapcsolatos információk jelentős részét, valamint a rendszer indítása során lefutó szkripteket. Egyes szkriptek a FreeBSD verzióiról verzióira változnak.

Némely konfigurációs állományok a rendszer hétköznapi működésében is szerepet játszanak. Ilyen például az `/etc/group`.

Alkalmanként a `make installworld` parancs futása során igényt tart adott nevű felhasználókra és csoportokra. A frissítéskor azonban ezek a felhasználók vagy csoportok nem feltétlenül állnak rendelkezésre, ami gondokat okozhat. Ezért bizonyos esetekben a `make buildworld` előzetesen ellenőrzi az igényelt felhasználók és csoportok meglétét.

Erre például szolgálhat a `smmsp` felhasználó esete. Nélküle a felhasználók nem tudták telepíteni az új rendszert, mert hiányában az mtree(8) nem volt képes létrehozni a `/var/spool/clientmqueue` könyvtárat.

Ezt úgy lehetett megoldani, hogy még az alaprendszer lefordítása (a `buildworld`) előtt meg kellett hívni a mergemaster(8) parancsot a `-p` paraméterrel. Így csak azokat az állományokat fogja összehasonlítani, amelyek feltétlenül szükségesek a `buildworld` vagy az `installworld` sikeres működéséhez. Amennyiben a `mergemaster` egy olyan verziójával rendelkezünk, amely nem ismeri a `-p` paramétert, akkor az első indításakor használjuk a forrásfában található újabb verzióját:

    # cd /usr/src/usr.sbin/mergemaster
    # ./mergemaster.sh -p

> Tipp: Ha különösen paranoiásak vagyunk, akkor a csoport törlése vagy átnevezése előtt az alábbi paranccsal ellenőrizni tudjuk az általa birtokolt állományokat:

>     # find / -group GID -print

> Ez megmutatja `GID` (mely megadható numerikus vagy név formájában is) jelzésű csoporthoz tartozó összes állományt a rendszerünkben.

## 24.7.5. Váltsunk egyfelhasználós módba

A rendszert egyfelhasználós módban érdemes lefordítani. A nyilvánvalóan érezhető gyorsaság előnyei mellett azért is jobban járunk, mert az új rendszer telepítése során számos rendszerszintű állomány is módosításra kerül, beleértve a szabványos rendszerszintű binárisokat, függvénykönyvtárakat, include állományokat és így tovább. Ha üzemelő rendszeren végezzük el mindezen változtatásokat (különösen amikor rajtunk kívül még további felhasználók is tartózkodnak a rendszerben), az csak a bajt hozza ránk.

Másik lehetőség gyanánt a rendszert magát lefordíthatjuk többfelhasználós módban is, majd ezután csak a telepítést hajtjuk végre egyfelhasználós üzemmódban. Ha eszerint cselekszünk, egyszerűen várjunk addig, amíg az összes fordítás be nem fejeződik, és az egyfelhasználósra váltást halasszuk a `installkernel` vagy `installworld` idejére.

Egy működő rendszerben rendszeradminisztrátorként az alábbi parancs kiadásával válthatunk át egyfelhasználós módba:

    # shutdown now

Ezt elérhetjük úgy is, ha újraindítjuk a rendszert és a rendszer indításakor a “single user” pontot választjuk a menüből. Ekkor a rendszer egyfelhasználós módban indul el. Miután ez megtörtént, adjuk ki a következő parancsokat:

    # fsck -p
    # mount -u /
    # mount -a -t ufs
    # swapon -a

Ezekkel a parancsokkal először ellenőrizzük az állományrendszereket, ezután újracsatlakoztatjuk a `/` állományrendszert írható módban, csatlakoztatjuk az `/etc/fstab` állományban megadott összes többi UFS típusú állományrendszert, majd bekapcsoljuk a lapozóállomány használatát.

> Megjegyzés: Ha a gépünk óráját nem a greenwich-i, hanem a helyi idő szerint állítottuk be (ez akkor áll fenn, ha a date(1) parancs nem a helyes időt és időzónát jelzi ki), akkor még erre is szükségünk lehet:

>     # adjkerntz -i

> Ezzel a helyi időzóna beállításait tudjuk jól beállítani -- nélküle később még gondjaink akadhatnak.

## 24.7.6. Töröljük a `/usr/obj` könyvtárat

A rendszer egyes részei fordításuk során a `/usr/obj` könyvtáron belülre kerülnek (alapértelmezés szerint). Az itt található könyvtárak a `/usr/src` könyvtárszerkezetét követik.

Ha mindenestől töröljük ezt a könyvtárat, akkor növeli tudjuk a `make buildworld` folyamat sebességét és megmenekülünk néhány függőségekkel kapcsolatos fejfájástól is.

Egyes `/usr/obj` könyvtáron belüli állományoknál szerepelhet a “megváltoztathatatlan” (immutable) állományjelző (lásd chflags(1)), amelyet a művelet elvégzéséhez először el kell távolítanunk.

    # cd /usr/obj
    # chflags -R noschg *
    # rm -rf *

## 24.7.7. Fordítsuk újra az alaprendszert

### 24.7.7.1. A kimenet elmentése

Jól járunk azzal, ha a make(1) futásának kimenetét elmentjük egy állományba, mivel így a hibák esetén lesz egy másolatunk a hibaüzenetről. Ha konkrétan nekünk nem is feltétlenül segít megtalálni a hiba tényleges okát, mások viszont többet tudnak róla mondani, ha beküldjük ezt a FreeBSD egyik levelezési listájára.

Ezt egyébként a legegyszerűbben a script(1) parancs segítségével oldhatjuk meg, amelynek paraméteréül azt az állományt kell megadni, ahova menteni akarjuk a kimenetet. Ezt közvetlenül a rendszer újrafordítása előtt kell kiadnunk, majd miután megállt, a `exit` paranccsal kiléphetünk belőle.

    # script /var/tmp/mw.out
    Script started, output file is /var/tmp/mw.out
    # make TARGET
    ... fordít, fordít, fordít ...
    # exit
    Script done, ...

Ilyenkor soha ne a `/tmp` könyvtárba mentsük a kimenetet, mert ennek a tartalma a következő indítás során magától törlődik. Sokkal jobban tesszük, ha a `/var/tmp` könyvtárba (ahogy tettük azt az előbbi példában is) vagy a `root` felhasználó könyvtárába mentünk.

### 24.7.7.2. Az alaprendszer fordítása

A `/usr/src` könyvtárban kell állnunk:

    # cd /usr/src

(kivéve természetesen, ha máshol van a forráskód, akkor abba a könyvtárba menjünk).

Az alaprendszert a make(1) paranccsal fordíthatjuk újra. Ez a `Makefile` nevű állományból olvassa be a FreeBSD programjainak újrafordítását leíró utasításokat, a fordításuk sorrendjét és így tovább.

A begépelendő paranccsor általános alakja tehát a következőképpen néz ki:

    # make -x -DVÁLTOZÓ target

A fenti példában a `-`x`` egy olyan a paraméter, amelyet a make(1) programnak adunk át. A make(1) man oldalán megtalálhatjuk az összes neki átadható ilyen beállítást.

A `-D`VÁLTOZÓ`` alakú paraméterek közvetlenül a `Makefile` állománynak adnak át olyan változókat, amelyek segítségével vezérelhető a viselkedése. Ezek ugyanazok a változók, mint amelyek az `/etc/make.conf` állományban is szerepelnek, és itt a beállításuk egy másik módját kapjuk. Így a

    # make -DNO_PROFILE target

paranccsal is megadhatjuk, hogy ne profilozott függkönyvtárak jöjjenek létre, ami pontosan megfelel a

    NO_PROFILE=    true 	#    Avoid compiling profiled libraries

sornak az `/etc/make.conf` állományban.

A `target` árulja el a make(1) programnak, hogy mi a teendője. Minden egyes `Makefile` különböző “targeteket” definiál, és a kiválasztott target mondja meg, pontosan mi is fog történni.

Egyes targetek ugyan megjelennek a `Makefile` állományban, azonban nem feltétlenül hivatkozhatunk rájuk közvetlenül. Ehelyett csupán arra valók, hogy a fordítás folyamatának lépéseit felbontsák még kisebb allépésekre.

A legtöbb esetben azonban semmilyen paramétert nem kell átadnunk a make(1) parancsnak, ezért a teljes formája így fog kinézni:

    # make target

ahol a `target` az egyik fordítási lehetőséget képviseli. Az első ilyen targetnek mindig a `buildworld`-nek kell lennie.

Ahogy a neve is mutatja, a `buildworld` lefordítja az összes forrást a `/usr/obj` könyvtárba, majd a `installworld` mint másik target, telepíti az így létrehozott elemeket a számítógépre.

A targetek szétválasztása két okból is előnyös. Először is lehetővé teszi, hogy az új rendszert biztonságban lefordíthassuk, miközben az a jelenleg futó rendszert nem zavarja. A rendszer tehát képes “saját magát újrafordítani”. Emiatt a `buildworld` target akár többfelhasználós módban is mindenféle nem kívánatos hatás nélkül használható. Ennek ellenére azonban továbbra is azt javasoljuk, hogy a `installworld` részt egyfelhasználós módban futtassuk le.

Másodrészt ezzel lehetőségünk nyílik NFS állományrendszer alkalmazásával több számítógépre is telepíteni hálózaton keresztül. Ha például három frissítendő számítógépünk van, az `A`, `B` és `C`, akkor az `A` gépen először adjuk ki a `make buildworld`, majd a `make installworld` parancsot. A `B` és `C` gépek ezután NFS segítségével csatlakoztatják az `A` `/usr/src` és `/usr/obj` könyvtárait, amelyet követően a `make installworld` paranccsal telepíteni tudjuk a fordítás eredményét a `B` és `C` gépekre.

Noha a `world` mint target még mindig létezik, használata határozottan ellenjavalt.

A

    # make buildworld

parancs kiadásakor a `make` parancsnak megadható egy `-j` paraméter is, amellyel párhuzamosíthatjuk a folyamat egyes részeit. Ez általában többprocesszoros számítógépeken nyer értelmet, azonban mivel a fordítás folyamatának haladását inkább az állományműveletek mintsem a processzor sebessége korlátozza, ezért alkalmazható akár egyprocesszoros gépeken is.

Tehát egy átlagos egyprocesszoros gépen így adható ki a parancs:

    # make -j4 buildworld

Ennek hatására make(1) egyszerre 4 szálon igyekszik működni. A levelezési listákra beküldött tapasztalati jellegű bizonyítékok azt igazolják, hogy általában ez a beállítás adja a legjobb teljesítményt.

Ha többprocesszoros géppel rendelkezünk és rajta SMP támogatású rendszermagot indítottunk el, akkor érdemes 6 és 10 közötti értékekkel kísérleteznünk.

### 24.7.7.3. Időigény

Számos tényező befolyásolja a fordítás tényleges időbeli hosszát, de a FreeBSD-STABLE fa lefordítása mindenféle trükkök és rövidítések nélkül a legtöbb számítógépen olyan egy vagy két órára taksálható. A FreeBSD-CURRENT fához ennél valamivel több időre lesz szükségünk.

## 24.7.8. Fordítsunk és telepítsünk egy új rendszermagot

Az újdonsült rendszerünket csak akkor tudjuk igazán kihasználni, ha egy új rendszermagot is készítünk hozzá. Ez gyakorlati szinten tulajdonképpen elvárás, mivel könnyen előfordulhat, hogy bizonyos memóriabeli adatszerkezetek felépítése megváltozott, ezért némely programok, mint például a ps(1) és top(1), egészen addig nem lesznek képesek normálisan működni, amíg a rendszer és a rendszermag forráskódja nem illeszkedik egymáshoz.

Ennek legegyszerűbb és egyben legbiztonságosabb módja, ha a `GENERIC` beállításai alapján gyártunk és telepítünk egy rendszermagot. Még ha a `GENERIC` beállításai nem is tartalmazzák a rendszerünkben fellelhető összes eszközt, minden megtalálható bennük ahhoz, hogy a rendszert sikeresen elindíthassuk legalább egyfelhasználós módban. Ez mellesleg remek próbája az új rendszer életképességének. Miután elindítottuk a rendszert a `GENERIC` típusú rendszermaggal és meggyőződtünk róla, hogy a rendszer tényleg működőképes, a megszokott rendszermagunk konfigurációs állománya alapján nyugodtan elkészíthetjük ezután azt is.

FreeBSD alatt egy új rendszermag építése előtt fontos újrafordítani az alaprendszert.

> Megjegyzés: Ha saját beállításaink szerint akarunk rendszermagot létrehozni és már van is ehhez egy konfigurációs állományunk, akkor erre használhatjuk a `KERNCONF=`SAJÁTMAG`` paramétert is, valahogy így:

>     # cd /usr/src
>     # make buildkernel KERNCONF=SAJÁTMAG
>     # make installkernel KERNCONF=SAJÁTMAG

Hozzátennénk, hogy ha a `kern.securelevel` rendszerváltozó értékét 1 felé állítottuk és a rendszermag állományának beállítottunk `noschg` vagy hozzá hasonló állományjelzőt, akkor az `installkernel` lefuttatásához mindenképpen egyfelhasználós módba kell váltanunk. Minden más esetben további bonyodalmak nélkül ki tudjuk adni az említett parancsokat. A `kern.securelevel` részleteiről az init(8) oldalán, a különböző állományjelzőkről pedig a chflags(1) oldalán olvashatunk.

## 24.7.9. Indítsuk újra a rendszert egyfelhasználós módban

Az új rendszermag működésének leteszteléséhez indítsuk újra a rendszert egyfelhasználós módban. Ennek pontos részleteit lásd 24.7.5 Szakasz.

## 24.7.10. Telepítsük az új rendszer binárisait

Ha a FreeBSD friss változatát nemrég fordítottuk le a `make buildworld` paranccsal, akkor utána az `installworld` segítségével tudjuk telepíteni a keletkezett programokat.

Tehát írjuk be ezeket:

    # cd /usr/src
    # make installworld

> Megjegyzés: Amennyiben a paranccsorban a `make buildworld` használata során adtunk meg változókat, akkor ne felejtsük el ugyanazokat megadni a `make installworld` kiadása során sem. Ez viszont a többi paraméterre már nem feltétlenül érvényes. Például a `-j` beállítást szigorúan tilos az `installworld` targettel együtt használni.

> Ennek megfelelően tehát ha korábban ezt írtuk be:

>     # make -DNO_PROFILE buildworld

> akkor így telepítsünk:

>     # make -DNO_PROFILE installworld

> Máskülönben azokat a profilozott függvénykönyvtárakat próbáljuk meg telepíteni, amelyek a `make buildworld` futása során nem jöttek létre.

## 24.7.11. Frissítsük a `make installworld` által kihagyott állományokat

Az alaprendszer újrafordítása nem regisztrálja az új vagy megváltozott állományokat bizonyos könyvtárakban (különösen értendő ez az `/etc`, `/var` és `/usr` esetén).

Az ilyen állományokat a legegyszerűbben a mergemaster(8) használatával tarthatjuk karban, de igény szerint akár kézzel is elvégezhetjük a szükséges aktualizálásokat. Függetlenül attól, hogy mit is választunk, mindenképpen készítsünk biztonsági mentést az `/etc` könyvtárról arra az esetre, ha bármilyen szörnyűség történne.

### 24.7.11.1. A `mergemaster`

Írta: Tom Rhodes.

A mergemaster(8) segédprogram valójában egy Bourne szkript, amely segít az `/etc` könyvtárunkban és a forrásfában levő `/usr/src/etc` könyvtárban elhelyezkedő konfigurációs állományok közti eltérések megállapításában. Ezt a módszert ajánljuk arra, hogy összevessük a konfigurációs állományainkat a forrásfában található változataikkal.

A használatának megkezdéséhez egyszerűen írjuk be, hogy `mergemaster`, majd várjunk egy kicsit, amíg a `mergemaster` létrehoz magának egy átmeneti környezetet a `/` könyvtárból elindulva és megtölti azt a különböző rendszerszintű beállításokat tartalmazó állományokkal. Ezeket az állományokat aztán összehasonlítja a jelenleg érvényben levő változataikkal. Ilyenkor a köztük talált eltéréseket a diff(1) formátumának megfelelően módon mutatja meg, ahol a `+` jelöli a hozzáadott vagy módosított sorokat, a `-` pedig a teljesen eltávolítandó vagy cserélendő sorokat. Erről a formátumról bővebben a diff(1) man oldalán találhatunk felvilágosítást.

A mergemaster(8) ezt követően megmutatja az összes olyan állományt, ahol eltérést tapasztalt, és ezen a ponton van lehetőségünk letörölni (delete) az új állományokat (amelyekre itt most ideiglenes állományként hivatkozik), telepíteni (install) a módosítatlan ideiglenes (új) állományt, valamint összefésülni (merge) az ideiglenes (új) és a jelenlegi állományokat, vagy ismét átnézni (view) a diff(1) által jelzett különbségeket.

Ha az ideiglenes állomány törlését választjuk, akkor a mergemaster(8) ezt úgy értelmezi, hogy változatlanul meg akarjuk tartani a jelenlegi változatot és törölni az újat. Ezt alapvetően nem javasoljuk, hacsak tényleg nem látunk valamilyen okot erre. A mergemaster(8) parancssorában a ? begépelésével bármikor kérhetünk segítséget. Ha az állomány kihagyását (skip) választjuk, akkor majd ismét felajánlja, amikor végeztünk az összes többivel.

A módosítatlan ideiglenes állomány telepítésének választásával lecseréljük a jelenleg verziót az újra. Ha az aktuális verziót sem változtattuk meg, akkor számunkra ez a legjobb megoldás.

Az állományok összefésülésének kiválasztásakor kapunk egy szövegszerkesztőt, benne a két állomány tartalmával. Ilyenkor tudjuk a képernyőn soronként egyeztetni a két állományt, majd a belőlük a megfelelő részek összeválogatásával kialakítani az eredményt. Ebben a feldolgozási módban az l (mint left, vagyis bal) billentyű lenyomására a bal oldalon látható részt, az r (mint right, vagyis jobb) lenyomására pedig a jobb oldalon látható részt választjuk ki. Az így keletkező eredményt ezután egy állományba kerül, amelyet telepíteni tudunk. Ez a megoldás olyan állományok esetében használható, amikor a felhasználó módosított az alapértelmezett beállításokat.

Ha a diff(1) szerinti alakban akarjuk átnézni a különbségeket, akkor a mergemaster(8) ugyanúgy megmutatja ezeket, mint a paranccsor megjelenítése előtt.

Miután a mergemaster(8) végigment a rendszerszintű állományokon, további opciókat mutat. Megkérdezheti, hogy újra létre akarjuk-e hozni a jelszavakat tároló állományt (rebuild), illetve a folyamat végén a megmaradt ideiglenes állományok törlésére (remove) vár választ.

### 24.7.11.2. Az állományok aktualizálása kézzel

Ha inkább manuálisan szeretnénk frissíteni, akkor nem másolhatjuk csak egyszerűen át az állományokat a `/usr/src/etc` könyvtárból a `/etc` könyvtárba és nem hagyhatjuk ezeket sorsukra. Egyes állományokat először “telepíteni” kell. Ez azért van így, mert a `/usr/src/etc` könyvtár nem pusztán az `/etc` könyvtár egyszerű másolata. Ráadásul az `/etc` könyvtárban vannak olyan állományok, amelyek a `/usr/src/etc` könyvtárban nem is találhatóak meg.

Ha (az ajánlottak szerint) a mergemaster(8) segítségével dolgozunk, nyugodtan átléphetünk a következő szakaszra.

Saját magunk a legegyszerűbben ezt úgy tudjuk megoldani, ha telepítjük az állományokat egy új könyvtárba és ezután nekiállunk változásokat keresni.

> Az `/etc` meglevő tartalmának mentése: Habár elméletileg magától semmi sem fogja bántani ezt a könyvtárat, azért ettől függetlenül mindig érdemes biztosra menni. Ezért másoljuk az `/etc` könyvtár tartalmát egy megbízható helyre. Például:

>     # cp -Rp /etc /etc.old

> Az `-R` itt a rekurzív másolást jelenti, a `-p` pedig a dátumok, az állományok és egyebek tulajdoni viszonyainak megőrzését.

Az `/etc` új változatának telepítéséhez szükségünk lesz még további könyvtárakra is. Erre a feladatra a `/var/tmp/root` tökéletesen megfelel, ahol még létre kell hoznunk néhány alkönyvtárat.

    # mkdir /var/tmp/root
    # cd /usr/src/etc
    # make DESTDIR=/var/tmp/root distrib-dirs distribution

Ezzel létrejön a szükséges könyvtárszerkezet és települnek az állományok. Sok üres alkönyvtár is keletkezik a `/var/tmp/root` könyvtáron belül, ezeket töröljük. Ezt a legkönnyebben így tehetjük meg:

    # cd /var/tmp/root
    # find -d . -type d | xargs rmdir 2>/dev/null

Ezzel törlődnek az üres könyvtárak. (A szabvány hibakimenetet átirányítottuk a `/dev/null` eszközre, és ezzel elnyomtuk a nem üres könyvtárak esetén keletkező hibaüzeneteket.)

A `/var/tmp/root` most már tartalmazza az összes olyan állományt, amelyek normális esetben a `/` könyvtáron belül foglalnak helyet. Ezt követően nincs más dolgunk, csak végigmenni az itt található állományokon és megállapítani, miben térnek a meglévőektől.

Vegyük észre, hogy a `/var/tmp/root` könyvtárba telepített állományok némelyikének neve “.”-tal kezdődik. Az írás pillanatában ezek csak a `/var/tmp/root/` és `/var/tmp/root/root/` könyvtárakban található parancsértelmezőhöz tartozó indító állományok lehetnek, habár adódhatnak még ilyenek (attól függően, mikor olvassuk ezt). Ezért a feldolgozásukhoz ne felejtsük el a `ls -a` parancsot használni.

A diff(1) alkalmazásával legegyszerűbben így tudunk összehasonlítani két állományt:

    # diff /etc/shells /var/tmp/root/etc/shells

Ennek hatására megjelennek az `/etc/shells` és az új `/var/tmp/root/etc/shells` állományok közti különbségek. A segítségével gyorsan el tudjuk dönteni, hogy összefésüljük-e a két állományt, vagy csak egyszerűen írjuk felül a régebbi verziót az újjal.

> Az új könyvtár (`/var/tmp/root`) nevébe írjuk bele a dátumot is, így könnyedén össze tudunk hasonlítani több verziót is: A rendszer gyakori újrafordítása az `/etc` szintén gyakori aktualizálását is maga után vonja, ami viszont fárasztó lehet.

> Az iménti folyamatot fel tudjuk gyorsítani, hogy ha az `/etc` legutoljára összefésült változatát megtartjuk. A most következő eljárás ennek mikéntjét vázolja fel.

> 1. A megszokottak szerint fordítsuk le a rendszert. Majd amikor az `/etc` könyvtárat és a többit is frissíteni akarjuk, a célként megadott könyvtár nevében adjuk meg a dátumot. Ha tehát például 1998. február 14. van, akkor írjuk ezt:

>        # mkdir /var/tmp/root-19980214
>        # cd /usr/src/etc
>        # make DESTDIR=/var/tmp/root-19980214 \
>            distrib-dirs distribution

> 2. Fésüljük össze a könyvtárban található az állományokat a fentiekben körvonalazottak szerint.

>    Befejezés után őrizzük meg a `/var/tmp/root-19980214` könyvtárat.

> 3. Mikor újra letöltjük a legfrissebb forrásokat és megismételjük az előbbi lépéseket, haladjunk megint az első lépés szerint. Ekkor tehát létrejön egy újabb könyvtár, amelynek a neve ezúttal már `/var/tmp/root-19980221` lesz (ha például hetente frissítünk).

> 4. Most már meg tudjuk vizsgálni a közbeeső héten született eltéréseket, ha a két könyvtárra kiadunk egy rekurzív diff(1) hívást:

>        # cd /var/tmp
>        # diff -r root-19980214 root-19980221

>    Általában így kevesebb eltérést kapunk, mint amennyi például a `/var/tmp/root-19980221/etc/` és az `/etc` összehasonlítása során elkerült volna. Mivel kisebb a keletkezett különbségek száma, ezért könnyebb lesz átvinnünk az `/etc` könyvtárunkba is a módosításokat.

> 5. Ezután törölhetjük a régebbi `/var/tmp/root-*` könyvtárat:

>        # rm -rf /var/tmp/root-19980214

> 6. Az `/etc` összefésülésekor mindig ismételjük meg ezeket a lépéseket.

> A date(1) meghívásával akár automatikussá is tehetjük a könyvtárak névadását:

>     # mkdir /var/tmp/root-`date "+%Y%m%d"`

## 24.7.12. Újraindítás

Ezzel készen is vagyunk. Miután ellenőriztük, hogy minden a megfelelő helyére került, indítsuk újra a rendszert. Ehhez egy egyszerű shutdown(8) is elegendő:

    # shutdown -r now

## 24.7.13. Befejeztük!

Gratulálunk, sikerült frissítenünk a FreeBSD rendszerünket.

Ha mégis valami balul ütne ki, könnyen újra tudjuk fordítani a rendszer egyes részeit. Például, ha véletlenül letöröltük az `/etc/magic` állományt az `/etc` frissítése vagy összefésülése során, a file(1) parancs nem fog tudni rendesen működni. Ilyenkor a következőket kell tennünk a hiba kijavításához:

    # cd /usr/src/usr.bin/file
    # make all install

## 24.7.14. Kérdések

24.7.14.1. Minden egyes változtatásnál újra kell fordítani a rendszert?
24.7.14.2. A fordító rengeteg 11-es jelzést (signal 11) (vagy másfajta jelzéseket) dob hibával. Mi történhetett?
24.7.14.3. A fordítása befejezése után törölhetem a `/usr/obj` könyvtárat?
24.7.14.4. Lehetséges a megszakadt fordítás folytatása?
24.7.14.5. Hogyan tudjuk felgyorsítani a fordítást?
24.7.14.6. Mi tegyünk, ha valami nem megy rendesen?

24.7.14.1. Minden egyes változtatásnál újra kell fordítani a rendszert?

Nem könnyű választ adni erre a kérdésre, mivel ez alapvetően a változtatás jellegétől függ. Például, ha elindítjuk a CVSup programot és csak az alábbi állományok frissülnek:

    src/games/cribbage/instr.c
    src/games/sail/pl_main.c
    src/release/sysinstall/config.c
    src/release/sysinstall/media.c
    src/share/mk/bsd.port.mk

Ekkor valószínűleg nem éri meg újrafordítani a teljes rendszert. Elegendő csupán belépni az érintett állományokat tartalmazó alkönyvtárakba és ott rendre kiadni a `make all install` parancsot. Ha viszont már valami komolyabb, például az `src/lib/libc/stdlib` változott meg, akkor vagy az egész rendszert, vagy legalább azon részeit fordítsuk újra, amely statikusan linkeltek (és minden más időközben még hozzáadott statikusan linkelt dolgot).

Hogy melyik megoldást választjuk, teljesen rajtunk áll. Újrafordíthatjuk az egész rendszert kéthetente, mondván, hadd gyüljenek fel szépen a módosítások, vagy a függőségek pontos kielemzésével csak azokat az elemeket fordítjuk újra, amelyek tényleg meg is változtak.

Természetesen az egész attól függ, hogy milyen gyakran és melyik rendszert, a FreeBSD-STABLE-t vagy a FreeBSD-CURRENT-et frissítjük.

24.7.14.2. A fordító rengeteg 11-es jelzést (signal 11) (vagy másfajta jelzéseket) dob hibával. Mi történhetett?

Ez általában hardveres meghibásodásra utal. A rendszer újrafordítása alapjaiban véve egy remek módszer számítógépünk alkatrészeinek terhelésére, ezért gyakorta előhozza a memória már meglevő hibáit. Ezek többnyire abban fogalmazódnak meg, hogy a fordító rejtélyes módon leáll mindenféle furcsa jelzések hatására.

Erről biztosan úgy tudunk meggyőződni, ha újraindítjuk a make programot és az a folyamat egy teljesen másik pontján vérzik el.

Ilyenkor nem tudunk mást tenni, mint egymás után kicserélgetjük, kivesszük az alkatrészeket és így próbáljuk megállapítani, pontosan melyikük is okozza a gondokat.

24.7.14.3. A fordítása befejezése után törölhetem a `/usr/obj` könyvtárat?

Röviden: Igen.

A `/usr/obj` tartalmazza a fordítás folyamata során keletkező összes tárgykódot. Ennek törlése általában a `make buildworld` első lépései között szerepel. Ezért tulajdonképpen a `/usr/obj` megtartásának nincs túlságosan sok értelme, viszont elég sok (jelenleg úgy kb. 340 MB) helyet fel tudunk így szabadítani.

Ha azonban értjük a dolgunkat, akkor megadhatjuk a `make buildworld` parancsnak, hogy hagyja ki ezt a lépést. Ennek hatására a fordítás sokkal hamarabb véget ér, mivel a legtöbb forrást így nem kell újrafordítani. Üröm az örömben, hogy ha netalán aprócska függőségi problémák merülnének fel, akkor az egész fordítás megfeneklik mindenfelé különös módokon. Emiatt gyakran írnak feleslegesen leveleket a FreeBSD levelezési listáira, melyek a rendszer sikertelen újrafordításáról panaszkodnak, miközben kiderül, hogy az maguk az érintettek akarták lerövidíteni a folyamatot.

24.7.14.4. Lehetséges a megszakadt fordítás folytatása?

Ez attól függ, hogy a probléma bekövetkezése előtt mennyire sikerült eljutni a fordításban.

Általában (tehát nem feltétlenül minden esetben) a `make buildworld` lefordítja a fordításhoz szükséges eszközök (például a gcc(1) és make(1)) újabb változatait és a rendszer függvénykönyvtárait, majd ezeket telepíti. Ezután ezekkel az új eszközökkel lefordítattja saját magukat és ismét telepíti. Ezt követően fordítja újra az új rendszerállományokkal az egész rendszert (így ezúttal már az olyan szokásos felhasználói programokat is, mint például az ls(1) és a grep(1)).

Ha tudjuk, hogy az utolsó fázisban álltunk le (mivel megnéztük a fordításhoz tartozó kimenetet), akkor (minden további nélkül) elég ennyi:

    ... kijavítjuk a hibát ...
    # cd /usr/src
    # make -DNO_CLEAN all

Ezzel megmarad a korábbi `make buildworld` munkájának eredménye.

Ha ezt az üzenetet látjuk a `make buildworld` kimenetében:

    --------------------------------------------------------------
    Building everything..
    --------------------------------------------------------------

akkor különösebb gond nélkül megcsinálhatjuk.

Amennyiben viszont nem látunk ilyen üzenetet, vagy nem vagyunk benne biztosak, akkor még mindig jobb elővigyázatosnak lenni, ezért kénytelenek leszünk teljesen elölről kezdeni a fordítást.

24.7.14.5. Hogyan tudjuk felgyorsítani a fordítást?

- Futtassuk egyfelhasználós módban.

- Tegyük a `/usr/src` és `/usr/obj` könyvtárakat külön állományrendszerekre, külön lemezekre. Sőt, ha lehetséges, akkor ezeket a lemezeket tegyük külön lemezvezérlőkre.

- Még mindig jobb, ha ezeket az állományrendszereket a ccd(4) (lemezek összefűzését vezérlő meghajtó) segítségével kiterjesztjük több lemezes eszközre.

- Kapcsoljuk ki a profilozást (az `/etc/make.conf` állományban a “NO_PROFILE=true” megadásával). Többnyire úgy sem lesz rá szükségünk.

- Az `/etc/make.conf` állományban a `CFLAGS` változót állítsuk az `-O -pipe` értékre. Az `-O2` gyakran sokkal lassabb, az `-O` és `-O2` alig tér el az optimalizálás mértékében. A `-pipe` paraméter hatására pedig a fordítóprogram átmeneti állományok helyett csöveket használ a kommunikációra, és így megtakarít némi lemezhasználatot (a memóriahasználat terhére).

- Ha a make(1) parancsnak átadjuk a `-j`n`` paramétert, akkor képes több mindent párhuzamosan futtatni. Ez sok esetben segít attól függetlenül, hogy egy- vagy többprocesszoros gépünk van.

- A `/usr/src` könyvtárat tartalmazó állományrendszert csatlakoztathatjuk (vagy újracsatlakoztathatjuk) a `noatime` beállítással. Ilyenkor az állományrendszer nem rögzíti a hozzáférés idejét. Erre az információra sincs igazából szükségünk.

      # mount -u -o noatime /usr/src

  > Figyelem: A fenti példa azt feltételezi, hogy a `/usr/src` könyvtárnak saját állományrendszere van. Ha ez nem így lenne (tehát például a `/usr` része), akkor itt azt kell megadnunk, nem pedig a `/usr/src` nevét.

- A `/usr/obj` könyvtárat tartalmazó állományrendszert csatlakoztathatjuk (vagy újracsatlakoztathatjuk) az `async` beállítással. Ennek hatására a lemez írása aszinkron módon történik. Magyarul az írási műveletek azonnal befejeződnek, miközben az adat ténylegesen csak pár másodperccel később kerül ki a lemezre. Ezzel az írási kérelmek gyönyörűen összegyűjthetőek, ami nagymértékű növekedést eredményez a teljesítményben.

  > Figyelem: Ne felejtsük el azonban, hogy ezzel együtt az állományrendszerünk is sérülékenyebbé válik. Ezen beállítás használatával megnő annak az esélye, hogy egy áramkimaradást követő indításnál az állományrendszer helyreállíthatatlan állapotba kerül.

  > Ha egyedül csak a `/usr/obj` található ezen az állományrendszeren, akkor ez nem jelent akkora veszélyt. Amikor viszont rajta kívül még értékes adat is található az állományrendszeren, a beállítás érvényesítése előtt mindenképpen készítsünk róla friss mentéseket.

      # mount -u -o async /usr/obj

  > Figyelem: Ahogy arról az előbb is szó esett, ha a `/usr/obj` nem egy különálló állományrendszeren található, akkor a példában szereplő csatlakozási pontot cseréljük ki a megfelelőre.

24.7.14.6. Mi tegyünk, ha valami nem megy rendesen?

Egyértelműen bizonyosodjunk meg róla, hogy a korábbi fordításokból nem maradtak vissza semmiféle kóbor állományok. Ennyi sokszor pontosan elég.

    # chflags -R noschg /usr/obj/usr
    # rm -rf /usr/obj/usr
    # cd /usr/src
    # make cleandir
    # make cleandir

Igen, a `make cleandir` parancsot tényleg kétszer kell kiadni.

Ezután a `make buildworld` parancstól indulva kezdjük újra a fordítást.

Ha még ezek után is fennáll a probléma, küldjük el a hibát tartalmazó kimenetet és a `uname -a` parancs eredményét a FreeBSD general questions levelezési lista címére. Ne lepődjünk meg, ha a beállításainkra vonatkozóan még kapunk további kérdéseket is!

Előző | Tartalom | Következő
A forrás szinkronizálása | Fel | A források követése több géppel

Ha kérdése van a FreeBSD-vel kapcsolatban, a következő címre írhat (angolul): <freebsd-questions@FreeBSD.org>.
Ha ezzel a dokumentummal kapcsolatban van kérdése, kérjük erre a címre írjon: <gabor@FreeBSD.org>.