Portál AbcLinuxu, 23. května 2024 09:47

Tvorba balíčků pro Solaris

13. 3. 2008 | Bob Koutský
Články - Tvorba balíčků pro Solaris  

Stejně jako různé distribuce Linuxu, i Solaris (a OpenSolaris) pro zjednodušení instalace softwaru používá balíčkovací systém. Ten vychází ze standardu System V R.4 (SVR4) a i když co do stáří je ve srovnání s některými linuxovými balíčkovacími systémy prakticky kmetem, jeho možnosti jsou opravdu rozsáhlé. Přitom však není nijak složitý ani pro administrátora, který balíčky instaluje, ani pro vývojáře, který je vytváří.

V tomto článku se zběžně podíváme, jak balíček na Solaris nainstalovat a odinstalovat, ale hlavně, jak jej snadno a rychle vyrobit. Jak už to samozřejmě u takovýchto článků bývá, berte jej pouze jako stručný úvod a ochutnávku možností. Mnohem víc informací najdete v manuálových stránkách a v Application Packaging Developer's Guide.

Úplné základy

Pokud chcete balíčky vytvářet, musíte je nejdřív umět instalovat a odstraňovat. Naštěstí je to v Solarisu opravdu jednoduché. Pro instalaci slouží pkgadd(1M), pro odstraňování ekvivalentně pkgrm(1M). Možná trochu neobvyklé může být, že pkgadd očekává, že je balíček uložen v adresáři /var/spool/pkg, takže pokud ho máte někde jinde, musíte příkaz na správnou cestu navést parametrem -d device, kde ono device znamená nejen třeba pásku, ale i normální soubor nebo adresář s balíčkem.

Solaris umí hlídat splnění potřebných závislostí mezi programy během instalace. Bohužel je stávající systém neumí automaticky naplňovat stahováním dalších potřebných závislostí z repozitářů. Počkejme si na další verzi...

Pro práci s balíčky slouží ještě několik dalších programů. Z těch nejdůležitějších jmenuji pkgchk(1M), který slouží pro kontrolu stavu nainstalovaných balíčků, a pkginfo(1), pomocí kterého můžete zjistit, které balíčky máte nainstalované a řadu podrobností o nich. Teď už se ale konečně podívejme, jak se tyto balíčky vlastně vytvářejí...

Hello, package!

Začneme jednoduše. Chceme vytvořit balíček, který bude obsahovat nejoblíbenější demonstrační program na světě a jeho manuálovou stránku. Jeho obsahem budou dva soubory, /opt/hello/bin/hello a /opt/hello/share/man/man1/hello.1. Pokud se ptáte, proč jsem zvolil adresář /opt, odpověd je snadná: je to jediné místo, kam se na Solarisu smí instalovat software, který není jeho součástí (viz [APGD]). Samozřejmě, pokud vytvoříte balíček, který bude instalovat soubory jinam, bude to fungovat a nemusíte se ani bát, že si pro vás přijde Solstapo, ale možná tím zkomplikujete situaci uživatelům, kteří na tuto konvenci spoléhají.

Forma

Ze všeho nejdřív vytvoříme pracovní adresář a v něm soubor pkginfo, který bude obsahovat základní informace o vytvářeném balíčku:

$ cat pkginfo
PKG=ABCLhello
NAME=The world famous hello world program.
ARCH=i386
VERSION=1.0
CATEGORY=application
BASEDIR=/opt

Opět asi netřeba podrobně vysvětlovat, co která řádka znamená, takže jen ty zajímavější věci:

Pochopitelně, pkginfo může obsahovat ještě řadu dalších informací, ty ale zatím vynecháme. Toto je příklad skoro minimálního pkginfo souboru, protože kromě BASEDIR jsou všechny ostatní řádky povinné.

Obsah

To, že známe název balíčku je sice super, ale bez souborů, které do něj patří, by to jaksi nebylo ono. K jejich specifikaci slouží soubor prototype, který nejsnáze vytvoříme pomocí příkazu pkgproto na základě existujícího adresářového stromu. Proto v našem pracovním adresáři vytvoříme strukturu odpovídající cílové struktuře adresářů a souborů nainstalovaného balíčku. Pokud všechny soubory, které chceme instalovat, mají společný prefix (jako v našem případě /opt), vynecháme jej:

$ find .
.
./hello
./hello/bin
./hello/bin/hello
./hello/share
./hello/share/man
./hello/share/man/man1
./hello/share/man/man1/hello.1
./pkginfo

Spustíme příkaz pkgproto, jako parametr mu zadáme náš pracovní adresář a jeho výstup uložíme do souboru prototype:

$ pkgproto . > prototype
$ cat prototype
d none hello 0755 jdoe other
d none hello/bin 0755 jdoe other
f none hello/bin/hello 0555 jdoe other
d none hello/share 0755 jdoe other
d none hello/share/man 0755 jdoe other
d none hello/share/man/man1 0755 jdoe other
f none hello/share/man/man1/hello.1 0644 jdoe other
f none pkginfo 0644 jdoe other

První položka označuje typ souboru. Zatím vidíme pouze typy "f" nebo "d", čili běžný soubor nebo adresář. Možností je o trochu víc, povíme si o nich za okamžik. Stejně jako o druhém poli, které určuje třídu souboru, v našem případě pouze "none". Zbytek asi nepotřebuje další komentář. Jen si všimněte, že pkgproto převzal informace o vlastnictví souboru z filesystému, takže pokud chcete, aby ve skutečné instalaci soubory patřily někomu jinému, nezapomeňte příslušné položky upravit, například takhle:

f none hello/bin/hello 0555 root staff

Kromě toho musíme udělat ještě jednu změnu, aby řádek pro soubor pkginfo vypadal takhle:

i pkginfo

Soubor pkginfo se totiž nakonec také octne v našem balíčku jako speciální informační soubor, proto musí být uveden v prototypu a označen speciálním typem "i".

Zkontrolujeme, že prototyp vypadá tak, jak má (třeba jestli v něm nepřebývají nějaké zapomenuté pomocné soubory, nebo jestli naopak nějaké soubory nechybějí) a můžeme se zaradovat, protože jsme na půl cesty k hotovému balíčku.

Asi nemusím příliš zdůrazňovat, že pkgproto je pouze pomocný nástroj a že pokud chcete, nic vám nebrání prototyp balíčku vytvořit ručně; ostatně, je to jen obyčejný textový soubor. Navíc většinou v něm stejně musíte provést nějaké změny, ať už je to prostá změna vlastníka souboru, nebo složitější nastavování typů a tříd. Je to ale užitečná pomůcka pro vytvoření počáteční verze prototypu, se kterou pak dále pracujete. Pokud se rozhodnete vytvořit prototyp ručně, nezapomeňte, že cesty v něm uvedené jsou relativní, tedy bez úvodního lomítka.

A jsme skoro hotovi! Už zbývá jen jeden příkaz:

$ pkgmk -r .
## Building pkgmap from package prototype file.
## Processing pkginfo file.
WARNING: parameter <pstamp> set to "deepone20071216233400"
WARNING: parameter <classes> set to "none"
## Attempting to volumize 7 entries in pkgmap.
part  1 -- 130 blocks, 10 entries
## Packaging one part.
/var/spool/pkg/ABCLhello/pkgmap
/var/spool/pkg/ABCLhello/pkginfo
/var/spool/pkg/ABCLhello/reloc/hello/bin/hello
/var/spool/pkg/ABCLhello/reloc/hello/share/man/man1/hello.1
## Validating control scripts.
## Packaging complete.
</classes></pstamp>

pkgmk dělá přesně to, co byste čekali podle názvu: vytvoří balíček. Parametr -r říká, kde je vrchol adresářové struktury, odkud bude brát soubory. Varování ve výstupu můžeme pokojně ignorovat, týkají se položek souboru pkginfo, které jsou volitelné, a pokud je neuvedeme, pkgmk použije rozumné výchozí hodnoty.

Náš balíček je hotov v adresáři /var/spool/pkg/ABCLhello (pokud se vám to nelíbí, určete jiné místo pomocí parametru -d). A jak že vypadá?

$ find /var/spool/pkg/ABCLhello
/var/spool/pkg/ABCLhello
/var/spool/pkg/ABCLhello/pkgmap
/var/spool/pkg/ABCLhello/pkginfo
/var/spool/pkg/ABCLhello/reloc
/var/spool/pkg/ABCLhello/reloc/hello
/var/spool/pkg/ABCLhello/reloc/hello/bin
/var/spool/pkg/ABCLhello/reloc/hello/bin/hello
/var/spool/pkg/ABCLhello/reloc/hello/share
/var/spool/pkg/ABCLhello/reloc/hello/share/man
/var/spool/pkg/ABCLhello/reloc/hello/share/man/man1
/var/spool/pkg/ABCLhello/reloc/hello/share/man/man1/hello.1

Pokud jste zvyklí na linuxové balíčky, možná jste překvapeni. Ano, solarisový balíček není jen jeden soubor, ale celá adresářová struktura s hejnem souborů, dokonce jeho podadresář reloc obsahuje doručované soubory s přesně takovým obsahem a na přesně stejné relativní pozici (vzhledem k BASEDIR), jak budou vypadat po instalaci.

Ono to má své výhody: informace o balíčku jsou snadno dostupné, můžete je zpracovávat standardními unixovými nástroji, do balíčku je prostě snadno vidět. Pochopitelně, v některých případech je pohodlnější, když je balíček jen jeden velký, pokud možno komprimovaný soubor. Proto Solaris zná druhý formát balíčku, takzvaný datastream format (tomu prvnímu se říká file system format), a je mezi nimi možno libovolně překládat příkazem pkgtrans:

$ pkgtrans -s /var/spool/pkg /tmp/ABCLhello.pkg ABCLhello
Transferring <ABCLhello> package instance
$ ls -l /tmp/ABCLhello.pkg
-rw-r--r--   1 jdoe other      61440 Dec 16 23:49 /tmp/ABCLhello.pkg

-s říká, že chceme konvertovat do datastream formátu, druhý a třetí jsou zdrojová a cílová lokace, v tomto případě je zdroj adresář a cíl soubor, za nimi následuje seznam balíčků, které se mají převést (ano, do jednoho souboru je možné uložit více balíčků).

A je to!

Přesně tak, hotovo. Nyní už stačí jenom baliček nainstalovat:

# pkgadd -d /var/spool/pkg ABCLhello

Processing package instance <abclhello> from

The world famous hello world program.(sparc) 1.0
Using </opt> as the package base directory.
## Processing package information.
## Processing system information.
## Verifying disk space requirements.
## Checking for conflicts with packages already installed.
## Checking for setuid/setgid programs.

Installing The world famous hello world program. as <ABCLhello>

## Installing part 1 of 1.
/opt/hello/bin/hello
/opt/hello/share/man/man1/hello.1
[ verifying class <none> ]

Installation of <ABCLhello> was successful.
# /opt/hello/bin/hello
Hello, world!
</none></abclhello>

Typy a třídy

Představme si, že dál pracujeme na našem mistrovském díle a po mnoha měsících usilovné práce do našeho programu přidáme možnost konfigurace kdovíčeho pomocí souboru /opt/hello/etc/hello.conf. Upravíme tedy číslo verze v pkginfo a přidáme do souboru prototype dva řádky:

d none hello/etc 0755 jdoe other
f none hello/etc/hello.conf 0555 jdoe other

Potom znovu vytvoříme balíček a rozešleme ho šťastným zákazníkům, kteří pomocí pkgrm odstraní starou verzi a pak nainstalují novou. Všechno funguje a svět je krásný. Pak ale zákazníci začnou být nešťastní, protože najdou v našem programu chybu. Chybu opravíme, a protože ještě neumíme patchovat (o tom bude další článek), vyrobíme další, třetí verzi balíčku, rozešleme ji zákazníkům a čekáme na jejich chválu. Té se ale nedočkáme, zákazníci jsou totiž pořád nešťastní. Proč? Inu, strávili spoustu času konfigurováním našeho programu, a když odinstalovali jeho druhou verzi aby mohli nainstalovat třetí, jejich pracně vytvořený konfigurační soubor zmizel. A kdo dneska zálohuje, že?

A to je chvíle, kdy nastupují výše zmíněné typy a třídy. Správně totiž nové položky v prototype měly vypadat takhle:

d none hello/etc 0755 jdoe other
e renameold hello/etc/hello.conf 0755 jdoe other
i i.renameold
i r.renameold

V řádku pro hello.conf jsme uvedli typ "e" a třídu "renameold". Typ "e" nebo "editable" znamená, že příslušný soubor může být modifikován uživatelem, sdílen s jinými programy, prostě že je potřeba k němu přistupovat opatrně. Co přesně ten "opatrný přístup" znamená, určíme pomocí konkretní třídy, kterou vytvoříme.

Název třídy můžeme zvolit libovolně, pokud možno výstižně. Pro každou třídu musíme vytvořit class action scripty, neboli skripty, které se postarají o správné doručení souboru na cílový počítač, případně o správné odstranění provedených změn při odinstalaci balíčku. Tyto skripty musejí být uvedeny v prototypu s typem "i" a jejich jména musí být i.jménotřídy pro instalační skript, respektive r.jménotřídy pro odinstalační skript.

Jak by mohly vypadat skripty pro naši třídu renameold?

$ cat i.renameold
#!/bin/sh
# Ano, /bin/sh, coz na Solarisu znamena stary dobry hloupy Bourne Shell,
# nikoliv BASH, jak jste mozna zvykli z Linuxu.
#
# Na vstupu skript obdrzi pro kazdy soubor jeden radek.
# Na kazdem radku je nejprve cesta k docasne kopii instalovaneho souboru,
# potom cesta kam se tento soubor ma nainstalovat.
while read src dst
do
  # Existuje uz cilovy soubor?
  if [ ! -f ${dst} ] ; then
    # Ne, tak to tam proste prekopirujeme.
    cp ${src} ${dst}
  else
    # Hm, existuje. Je stejny jako to co chceme instalovat?
    # Pokud ano, nemusime delat nic.
    cmp -s ${src} ${dst}
    if [ $? != 0 ] ; then
      # Neni stejny. Zazalohujeme jeho starou verzi.
      cp ${dst} ${dst}.old
      # Zkopirujeme novou verzi na spravne misto.
      cp ${src} $dst}
      # A dame o tom userovi vedet.
      echo "Existing file was renamed: ${dst} ${dst}.old"
    fi
  fi
done
exit 0

$ cat r.renameold 
#!/bin/sh
#
# Nedelame nic, proste nechame soubor jak je.

exit 0

Mimochodem, asi tušíte, co znamenala všechna ta none, která píšeme do pole pro název třídy u "obyčejných" souborů. To je základní třída, která prostě při instalaci soubor zkopíruje na jeho místo a při odinstalaci jej zase odstraní. Pro ni žádné class action skripty dodávat nemusíte, Solaris ji zvládne sám.

A hotovo. Pokud nainstalujeme tento balíček a pak jej odstraníme, konfigurační soubor zůstane na svém místě protože skript r.renameold nic nedělá. Když potom baliček nainstalujeme znovu, ať už stejnou nebo novější verzi, i.renameold se postará o to, aby stará verze byla zazálohována a až potom se nainstalovala nová.

Samozřejmě, že toto řešení není ideální, protože udržujeme jenom jednu záložní kopii souboru a uživatel musí ručně přenést své změny do nové verze. Je ale asi jasné, že trochu chytřejší instalační skript by se mohl pokusit přenést změny ze staré verze souboru do nové (a až když by to nezvládl, tak by provedl to co teď), v případě potřeby zkonvertovat konfigurační soubor ze starého do nového formátu a podobně. Možností je nespočetně. Každý speciální soubor má vlastní požadavky, které lze snadno řešit speciální třídou a příslušnými class action skripty.

Balíčkové skripty

Kromě jednotlivých doručovaných souborů s sebou balíček může nést i několik skriptů, které se spouštějí v různých okamžicích jeho instalace a odinstalace. Jejich použití shrnuje následující tabulka:

Skript Účel Smí modifikovat systém? Smí komunikovat s uživatelem? Smí ukončit instalaci?
request Získat dodatečné informace od uživatele. Ne Ano Ne
checkinstall Ověřit možné další podmínky pro instalaci balíčku. Poslední šance přerušit instalaci. Ne Ne Ano
preinstall Operace které je potřeba provést před instalací (např. pozastavení démonů). Ano Ne Ne
postinstall Operace které je potřeba provést po instalaci (např. znovuspuštění démonů). Ano Ne Ne
preremove Operace, které je potřeba provést před odinstalováním. Ano Ne Ne
postremove Operace, které je potřeba provést po odinstalování. Ano Ne Ne

Stejně jako class action skripty, i tyto skripty musejí být uvedeny v prototypu s typem "i". Takže kdybychom chtěli v našem balíčku po instalaci restartovat příslušného démona, přidáme postinstall skript. prototype pak bude vypadat takhle:

d none hello 0755 jdoe other
d none hello/bin 0755 jdoe other
f none hello/bin/hello 0555 jdoe other
d none hello/share 0755 jdoe other
d none hello/share/man 0755 jdoe other
d none hello/share/man/man1 0755 jdoe other
f none hello/share/man/man1/hello.1 0644 jdoe other
d none hello/etc 0755 jdoe other
e renameold hello/etc/hello.conf 0755 jdoe other
i i.renameold
i r.renameold
i postinstall
i pkginfo

Skript sám pak bude velmi jednoduchý:

$ cat postinstall
#! /bin/sh

# Pouzivate prece SMF, ne?
svcadm restart hellod

Kam dál?

Jak už jsem napsal úvodem, tento článek byl jenom velmi stručným úvodem do balíčkovacího systému Solarisu, podrobnější informace najdete ve výborné dokumentaci a manuálových stránkách, které popisují nejen příkazy jako pkgmk(1) nebo pkgproto(1), ale i formáty souborů jako prototype(4) nebo pkginfo(4). Doufám ale, že se mi podařilo ukázat, jak jednoduchý a současně mocný systém to je a že jsem ve vás probudil aspoň jiskřičku zájmu. Pokud ano, můžete se těšit na další článek, tentokrát o patchování.

Související články

Solaris patchování - opravy nainstalovaných balíčků
Solaris 10 a zóny
Co je na tom Solarisu 10 tak úžasného!?
OpenBoot Prompt
Java pod GPL

Odkazy a zdroje

Application Packaging Developer's Guide
Solaris
OpenSolaris

Další články z této rubriky

Úvod do Dockeru (1)
Paralelizace běžných činností v konzoli pomocí GNU Parallel
Unixové nástroje – 26 (triky pro práci v Bashi)
Unixové nástroje – 25 ((s,c)fdisk, gdisk, parted a findmnt)
Linux: systémové volání splice()

Diskuse k tomuto článku

13.3.2008 07:49 burlog
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
Odpovědět | Sbalit | Link | Blokovat | Admin
Manualnich strankach? Co to je :-D
13.3.2008 08:38 Robert Krátký | skóre: 94 | blog: Robertův bloček
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
Chybka.
13.3.2008 10:23 burlog
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
Jasne :-), ale krasna...
David Ježek avatar 13.3.2008 12:53 David Ježek | skóre: 83 | blog: Mostly_IMDB
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
to bezesporu, já bych ji klidně zachoval jakožto dokonalý vtípek, který každý musí pochopit :-)
14.3.2008 16:06 zde | skóre: 9 | blog: Linuch | Brno
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
Odpovědět | Sbalit | Link | Blokovat | Admin
Článek výbornej, ale popisovaný balíčkovací systém IMHO za moc nestojí, ty nástroje vypadají hodně nešikovné.
Táto, ty de byl? V práci, já debil.
14.3.2008 17:01 Jan Horak
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
Odpovědět | Sbalit | Link | Blokovat | Admin
Peknej clanek, ale celej ten system je k nicemu.

Uz jsem se malem smiril s tim, ze neexistuje nadstavba ani centralni repository balicku jako u jinych distribuci a potom jsem prisel na to, ze polozka 'ARCH' se pri instalaci nekontroluje, takze muzete nainstalovat cokoliv kamkoliv a pak uz se jenom divite co ze se to vlastne deje - hruza.

Kdepak, od tohohle ruce pryc.
21.3.2008 13:24 Hlipa
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
Mozna pomuze toto: http://www.par.univie.ac.at/solaris/pca/. Je to sice na patche, ale i to je samostatna kapitola. Co se tyce repository, tak existuje blastwave, kde je mozno najit spoustu baliku a je tu k tomu utilitka pkgget.
21.3.2008 18:25 Milan Jurik | skóre: 21 | blog: Komentare | Ova
Rozbalit Rozbalit vše Re: Tvorba balíčků pro Solaris
ARCH se nekontroluje pri instalaci, protoze stale jeste existuji diskless klienti... Tzn. SPARC server muze obsahovat strom s x86 instalaci a tu dorucovat x86 diskless stanicim. Jsou uzivatele, ktere tohle berou jako vyhodu. Ja osobne ne, uz jsem take si nainstaloval x86 balicek na SPARCa omylem.

Ano, centralni repository neexistuje, nekdo uziva Blastwave, nekdo sunfreeware, bohuzel nikdo nemel zajem na poradne nadstavbe ala apt-get nad dpkg, lepsi nez je pkg-get.

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.