Portál AbcLinuxu, 5. května 2025 13:19
Solaris používá balíčkovací systém Systemu V release 4 (SVR4), jehož základní principy a postupy byly popsány v článku Tvorba balíčků pro Solaris. Tentokrát vás uvedu do navazující problematiky doručování oprav do nainstalovaných balíčků, tedy patchování.
Podívejme se, co dělá patch patchem:
Od pohledu je zřejmé, že patchování není věc u celé řady systémů běžná a že se jedná o vlastnost, kterou ocení zejména administrátoři. Zajímavá je možnost doručení nezbytného minima pro opravu konkrétní chyby. Ponechání ostatních částí netknutých snižuje rizika, která s sebou do systému přináší každá změna. Neméně důležitá je také možnost v případě selhání patch vyjmout a vrátit systém do původního stavu. SVR4 balíčkovací systém tedy zná dvě základní akce: instalaci balíčku nebo jeho upgrade formou nové verze (tato vlastnost je společná s mnoha jinými balíčkovacími systémy) a doručení opravy do stávajícího balíčku (vlastnost méně obvyklá), včetně správy takto doručených oprav a možnosti návratu zpět.
Jak to celé funguje? Patch pro Solaris je část balíčku (sparse package) nebo jejich sada obsahující k doručení pouze změněné objekty. Kromě doručování cílených oprav stojí za touto praxí také historický důvod - snaha ušetřit objem přenášených dat na nezbytné minimum. Balíček totiž může být kompletní a pokud by byly nezměněné objekty zcela identické (tj. nebyly ani překompilovány) s těmi, jež se v systému již nacházejí, byly by během instalace patche ignorovány. Balíčky v patchi se musejí shodovat s těmi, které jsou nainstalované na systému, v názvu, verzi a architektuře.
Pro každý jeden je pak při běhu patchadd(1M) zavolán pkgadd(1M). Jednotlivé skripty obsažené v balíčcích v sobě nesou základní logiku pro kontrolu, zda-li je možné daný patch aplikovat, i když tento úkol dnes vykonává sám patchadd. Stále je však klíčovou funkcí těchto skriptů připravení a archivace informace potřebné pro návrat k předchozímu stavu - vytvořit tzv. "backout" balíček. Při běhu patchrm(1M) se pak provede pkgadd(1M) "backoutových" balíčků.
Aby bylo zaručeno fungování patche, musejí balíčky obsažené v patchi obsahovat více metadat, než je nezbytné pro běžný SVR4 balíček. Podívejme se na základní rozdíly a rozdělení jednotlivých úkolů.
Soubor se musí shodovat s původním balíčkem v hodnotách zapsaných pro PKG, VERSION a ARCH, kterými je jednoznačně identifikována konkrétní verze balíčku. Kromě toho však musí navíc obsahovat definici SUNW_PATCHID pro identifikaci patche. A dále může definovat ještě SUNW_OBSOLETES, SUNW_REQUIRES a SUNW_INCOMPAT, kterými lze upravit vztah k patche k patchům ostatním. Předpona "SUNW_" (odpovídající původnímu symbolu akcií Sunu) je v současné implementaci povinná v této podobě. Důležité je také nezapomenout nastavit správně hodnotu CLASSES (tj. tak, aby obsahovala všechny třídy, které se nacházejí v pkgmap balíčku), aby se nám nestalo, že se instalace některých souborů vůbec nespustí.
Běžný checkinstall skript kontroluje, zda-li je možné balíček bezpečně nainstalovat, a jako jediný může zcela bezpečně instalaci ukončit. To platí pro patch. V tomto případě však navíc připravuje s patchem související hodnoty pro soubor pkginfo a ukládá je do souboru odpovědí ("response file"), tj. souboru, jehož jméno bylo předáno v prvním parametru a který je následně načítán před spuštěním ostatních skriptů během instalace.
Tento skript se při instalaci patche spouští dvakrát. Nejprve proběhnou checkinstall skripty ze všech balíčků (tzv. dryrun) a potom je spouštěn jako běžná součást průběhu pkgadd(1M).
Připraví strukturu "backout" balíčku a zaplní jej příslušnými metadaty. Obsah adresáře install/ tohoto balíčku je vytvořen ze skriptů obsažených v patchi, které mají buď předponu "patch_" nebo "u.", a to tak, že předpona "patch_" je odstraněna a metadata přenesena do "backout" balíčku. U skriptů pojmenovaných "u.*" je předpona nahrazena "i." a jsou použity jako instalační (class action) skripty.
Kromě této základní struktury se v preinstall skriptu také ukládají informace o všech nesouborových objektech doručovaných daným patchem (jako linky, pojmenované roury, soubory zařízení), pro jejichž doručení se nespouští žádný další (class action) skript, ale jsou vytvářeny přímo programem pkgadd(1M).
Stejně jako v běžném balíčku jsou právě tyto skripty zodpovědné za doručení vlastního obsahu do souborového systému. Kromě toho o každém doručovaném souboru pořizují záznam do "backout" balíčku. Tzn. pokud objekt před doručením v systému existoval, uchovají jeho kopii. Pokud je nově instalován, je označen k odstranění při případném odinstalování patche.
postinstall skript zpracuje soubor deletes, pokud jej metadata balíčku v patchi obsahují. Tedy uchová kopii pro odinstalování patche. V databázi systému jej odstraní z vlastnictví příslušného balíčku a pokud po této akci žádnému dalšímu balíčku nepatří, smaže jej ze souborového systému.
Druhým úkolem tohoto skriptu je vytvořit vlastní "backout" balíček na základě dosud posbíraných dat. Takto rozvržené pořadí činností je také důvodem, proč je důležité, aby skripty v patchi po proběhnutí checkinstall neukončily činnost s nenulovou návratovou hodnotou, dokud neměl postinstall šanci skončit s výrobou dat pro návrat k původnímu stavu, aby i v případě selhání byla zajištěna možnost odstranění změn.
Jak jsme si již ukázali, metadata "backout" balíčku jsou zajištěna pomocí skriptů s předponou "patch_" a "u.". Také odstraněni patche (tedy vlastně instalace "backout" balíčku) vyžaduje provedení některých činností.
patch_checkinstall má dle očekávání za úkol zkontrolovat, že patch lze bezpečně odstranit. Tedy zejména, že již nebyl nainstalován stejný patch vyšší revize. Kromě toho (podobně jako protějšek při instalaci patche) připravuje související pkginfo data.
Zajišťuje doručení objektů patřících příslušné třídě uložených v "backout" balíčku.
Podobně jako při instalaci patche patch_postinstall zajišťuje zpracování souboru deletes, tj. odstraní záznam o vlastnictví objektu, případně jej smaže úplně, pokud se k němu nehlásí žádný další balíček. Kromě toho pak patch_postinstall zajišťuje smazání dat uložených pro odinstalování patche.
Poznámka ke skriptům: Bohužel, vzhledem k tomu, že Solaris Express a OpenSolaris běžně patche nepoužívají, tak konkrétní implementace těchto skriptů, ač veřejně přístupná v každém patchi, nebyla dosud uvolněna pod žádnou ze svobodných licencí. Jejich starší verze však byla v plné podobě zveřejněna a doporučena v dokumentu "Application Packaging Developer's Guide". Tato jejich podoba je také v přiloženém archívu.
Kromě odlišnosti na úrovni jednotlivých balíčku musí každý patch ve svém kořenovém adresáři obsahovat soubor .diPatch, který signalizuje, že se jedná o "direct instance" patch. Tento typ patchů, jenž spočívá v zachování verze (instance) balíčku během patchování, se v Solarisu používá od verze 2.5, kdy nahradil starší model progresivního patchování zvyšujícího při aplikaci patche verzi balíčku nainstalovaného na systému.
Ve svém kořenovém adresáři by měl patch obsahovat také soubor README.<číslo_patche> a volitelně může obsahovat metadata patche používaná nástroji pro automatizaci v podobě souboru patchinfo.
Nakonec může mít speciální patch skripty prepatch, postpatch, prebackout a postbackout, které se spouštějí před a po instalaci nebo odstranění patche. Jejich použití je však rozumné se vyhnout. Toto řešení totiž nedostatečně škáluje v prostředí, kde je potřeba vyrábět a spravovat velké množství patchů. A na rozdíl od skriptů v balíčcích je potřeba doplnit logiku, která zajistí provedení akce pouze ve správném kontextu při různých scénářích instalace.
Pro vzájemné vztahy mezi patchi existuje několik jednoduchých pravidel. Patche jsou kumulativní. Tzn. každá nová revize obsahuje nové opravy a opravy všech revizí předchozích.
Jeden soubor typu "f" nesmí být současně doručován více než jedním patchem. Pokud má nový patch doručovat "f" objekt již obsažený v patchi jiném, musí nový patch ten původní buď nahradit (SUNW_OBSOLETES), nebo na něm záviset (SUNW_REQUIRES), aby bylo zajištěno, že nedojde k regresi daného souboru nesprávným pořadím instalace patchů. Nová revize patche je chápána jako implicitní nahrazení revize předchozí - nástroje na instalaci patchů proto neumožní nainstalovat starší revizi přes novější.
Kruhové závislosti jsou nepřípustné. Tedy nelze nastavit závislosti dvou nebo více patchů tak, aby se pro instalaci vyžadovaly navzájem.
šablony skriptů (tar.gz)
LAB (tar.gz)
A o dokonalosti bych ani nemluvil, protoze patche nelze odinstalovavat. Teda ono to jde, ale znicite si tim system, bohuzel - a navic je idinstalovani patche nepodporovana akce.FUD? Uved cislo patche, ktery ti po backoutu znicil system. A taktez support kontakt, ktery uvedl, ze patch backout neni podporovana akce, aby byl briskne poslan na skoleni.
Dobry den, zrejme jsem vas pobouril, ale to rozhodne nebylo mym umyslem pouze jsem se nechal unest moji spatnou zkusenosti s instalaci patchu (predevsim dobou instalace). Rad bych tedy neco dodal: - patche jsou potrebne - na solarisu jsou bohuzel hodne moc pomale (opravdu hodne pomale)Doba instalace je dana designem, na kterem by slo asi kde co zlepsit... Vzdy bude pomalejsi nez instalace balicku stejne velikosti, protoze patch musi toho vykonat prece jen o neco vice.
Co se tyka onoho supportu, tak mi to nikdo nerekl, ale nekde jsem to cetl jenze uz je to davno, tak vam bohuzel nepovim kde a je klidne mozne, ze se jednalo pouze o jeden zminovany patch, ktery se nesmi odinstalovat, ale nanestesti jsem si to zapamatoval jako obecne pravidlo - proste opravdu nevim a takhle mi to utkvelo v pameti. Kazdopadne dekuji za opravu.Samozrejme si nepamatuju celou historii Solarisich patchu, takze nepochybne mohly existovat patche, ktere nelze backoutovat, ale spise to budou patche, ktere se nedoporucuje backoutovat. Obecne je kazdy patch opakovane testovan na instalaci a backout pred svym uvolnenim.
A ktery ze patch mi znicil system? I to uz je davno, ale nasel jsem jeste zapisky, takze ani to neni jiste, ale skoncil jsem nekde u odebirani patchu 125100-05 a 125075-01. Pred nimi jsem ovsem odebral jeste dalsi vetsi mnozstvi patchu: 125166-02 119130-33 120222-16 119974-07 120182-05 120346-07 120348-02 a nasledne jeste 124250-03 121132-02 125427-01 125424-01 125329-02 125120-01 125116-01 125100-05 125075-01 - zde me poznamky konci, takze jeden z techto poslednich dvou patchu zpusobil nefunkcnost systemu (ovsem mozna az po nalsednem rebootu)Koukam, ze jste tehdy pekne rezal do systemu
Ovsem jelikoz jsem to zkousel jiz hodne davno, tak opravdu nevim jestli to bylo pri tomhle pokusu, nebo pri nejakem jinem, ale bylo to nejspis pri tomhle.Vzpomenete si na to, v jakem stavu ten system byl? Co presne znaci "znicil system"? Pri tomhle mnozstvi backoutovanych patchu je treba postupovat hodne pomalu zpet a pokud neco takoveho potrebujete delat vicekrat, zvazil bych spise uzivani live upgrade/patching.
Doufam, ze se mi timto podarilo tento neumyslny flame uzavrit a uvest na pravou miru co jsem chtel a take mel puvodne rici. S pozdravem, Jan Horak.Nepovazuji to za flame, ocenuji vase informace. Skoda, ze jste to tehdy neeskaloval na support, protoze backout patche, pokud postupujete podle README (u backoutu vyrazne doporucuji, je to delikatnejsi operace), je opravdu podporovanou veci a nefunguje-li, mel by jste Sun nedecentne upozornit.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.