V článku bude demonstrováno použití mock a standardního FTP/HTTP serveru pro možnost tvorby vlastního repozitáře. Toto může být vhodné pro případ, že není možné z licenčních či jiných důvodů (např. konflikt s existujícím balíkem) využít poskytované služby build service (openSUSE nebo Fedora).
Úvod
Mock je nástroj využívaný distribucích založených na RPM/YUM (Fedora, CentOS, RHEL) k sestavování RPM balíčků v chroot prostředí. Na jednom systému můžeme vytvářet balíčky pro různé distribuce a někdy i pro různé architektury (např. i686 a x68_64).
Pro podrobnější studium mohu doporučit následující odkazy:
- Projects/Mock
- Using Mock to test package builds
- Mock Setup Using Local Mirror
- Building RPMs using Mock
Většinu věcí se při práci s mock je možno provádět pod běžným uživatelským účtem. Zde budeme používat tuto konvenci: pokud budou potřeba vyšší oprávnění (root), bude použit příkaz "sudo", ale je možné to dělat i
přepnutím na root pomocí "su".
Instalace
mock budeme instalovat v distribuci Fedora 17 a balíčky budeme vytvářet pro CentOS 5 a CentOS 6, resp. pro Fedoru. Nejprve nainstalujeme potřebné balíčky:
sudo rpm -ivh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm \ http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm sudo yum install mock.noarch \ mock-rpmfusion-free.noarch mock-rpmfusion-nonfree.noarch \ fedora-packager.noarch
Příprava prostředí
Aby mohl celou úlohu provádět i někdo další, bude popsána pomocí proměnných. Pokud je nastavíme dle svého, další postup již můžeme využít beze změn. Provedeme tedy nastavení proměnných použitých pro instalaci i konfiguraci.
MOCKCFGDIR="/etc/mock" MOCKDIR="/export/mock" MOCKBASEDIR="${MOCKDIR}/base" MOCKCACHEDIR="${MOCKDIR}/cache" REPOBASEDIR="${MOCKDIR}/repo" MYMOCKUSER=franta FTPSERVER="ftp1.mojefirma.cz" FTPSERVERSSH="22" FTPBASEDIR="/var/ftp/pub/mojefirma" FTPSERVERMIRRORS="ftp2.mojefirma.cz ftp3.mojefirma.cz"
Potřebujeme tedy běžného uživatele, který bude balíčky vytvářet - musí být členem skupiny mock. Vytvoření uživatele, pod kterým budeme vše ostatní provádět:
sudo useradd -m -G mock $MYMOCKUSER
nebo přidání aktuálně přihlášeného uživatele do skupiny mock:
MYMOCKUSER=$LOGNAME sudo usermod --append --groups mock $MYMOCKUSER
Bude nutné nové přihlášení pod účtem $MYMOCKUSER a nové nastavení proměnných:
su - $MYMOCKUSER
a nastavení práv:
sudo chown -R :mock ${MOCKCFGDIR} sudo chmod -R g+w ${MOCKCFGDIR}
Nastavení práv by mohlo jít i s pomocí ACL, ale to nemusí fungovat:
# sudo setfacl -d -m g:mock:rwx ${MOCKCFGDIR} # sudo setfacl -R -m g:mock:rw ${MOCKCFGDIR}/*
Vytvoříme kompletní adresářovou strukturu pro repozitář pro dvě distribuce: CentOS 5/6 a Fedora 17/18 a 3 varianty: os, updates, testing:
if [ ! -d "$REPOBASEDIR" ] ; then sudo mkdir -p "$REPOBASEDIR" fi for dist in fedora ; do for distnr in 17 18 ; do for repotype in os updates testing ; do sudo mkdir -p ${REPOBASEDIR}/${dist}/${distnr}/${repotype}/{i386/RPMS,x86_64/RPMS,SRPMS} done done done for dist in centos ; do for distnr in 5 6 ; do for repotype in os updates testing ; do sudo mkdir -p ${REPOBASEDIR}/${dist}/${distnr}/${repotype}/{i386/RPMS,x86_64/RPMS,SRPMS} done done done sudo chgrp -R mock ${REPOBASEDIR} sudo chmod -R g+w ${REPOBASEDIR}
Upravíme nastavení mock v ${MOCKCFGDIR}:
cp ${MOCKCFGDIR}/site-defaults.cfg ${MOCKCFGDIR}/site-defaults.cfg-orig sed -e "s@# config_opts\['basedir'\] = '/var/lib/mock/'@config_opts['basedir'] = '${MOCKBASEDIR}'@" \ -e "s@# config_opts\['cache_topdir'\] = '/var/cache/mock'@config_opts['cache_topdir'] = '${MOCKCACHEDIR}'@" \ ${MOCKCFGDIR}/site-defaults.cfg-orig > ${MOCKCFGDIR}/site-defaults.cfg sudo mkdir -p ${MOCKBASEDIR} ${MOCKCACHEDIR} sudo chgrp mock ${MOCKBASEDIR} ${MOCKCACHEDIR} sudo chmod -R g+rws ${MOCKBASEDIR} ${MOCKCACHEDIR}
Je nutné importovat všechny GPG klíče do RPM:
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-*
Vytvoříme chroot stromy (možnosti lze vybrat podle konfiguračních souborů uložených v ${MOCKCFGDIR}). Varianta pro tvoru balíků založených na repozitářích Fedora:
mock -r fedora-17-i386 init mock -r fedora-17-x86_64 init mock -r fedora-18-i386 init mock -r fedora-18-x86_64 init
Varianta pro tvoru balíků založených na repozitářích EPEL (včetně CentOS):
mock -r epel-5-i386 init mock -r epel-5-x86_64 init mock -r epel-6-i386 init mock -r epel-6-x86_64 init
Pokud chceme námi vytvořené balíky využívat k tvorbě dalších, musíme naše repozitáře přidat také. Zkopírujeme konfiguraci z ${MOCKCFGDIR}/epel*, přidáme část s naším repozitářem a pak můžeme provést init.
mock -r mojefirma-epel-5-i386 init mock -r mojefirma-epel-5-x86_64 init mock -r mojefirma-epel-6-i386 init mock -r mojefirma-epel-6-x86_64 init
Tvorba balíčku
Vytvoření zdrojového balíčku
POZOR! Kvůli novému RPM (F11 a výše, tj. CentOS 6 a výše) je potřeba src.rpm balíčky pro EPEL a CentOS vytvářet pomocí upraveného skriptu rpmbuild-md5, jinak selže rozbalování rpm v chroot buildu. Balíčků pro F11 a výše se toto upozornění netýká.
Musíme nastavit pracovní adresář:
cd ~/rpmbuild/SPECS
Sehnat zdrojové soubory pro daný SW a vytvořit .spec soubor:
vim mod_auth_pgsql.spec
Zkusit přeložit balíček na vlastní platformě:
rpmbuild-md5 -ba mod_auth_pgsql.spec
Není nutné balíček cvičně překládat, stačí upravit .spec a vytvořit pouze src.rpm, např. takto (je vhodné i s parametrem --nodeps):
rpmbuild-md5 --nodeps -bs mod_auth_pgsql.spec
Překlad balíčku pro jedinou platformu
Toto je vhodné dělat pro úvodní překlad, kde se testují potřebné závisloti apod.
Příklad pro základní distribuci s balíčky EPEL
mock rebuild -r epel-5-i386 /usr/src/redhat/SRPMS/mod_auth_pgsql-2.0.3-2.f17.src.rpm
Překlad balíčku pro všechny vyjmenované platformy
překlad nějakého balíčku pro vyjmenované distribuce
srcrpmpath=~/rpmbuild/SRPMS/mod_auth_pgsql-2.0.3-2.f17.src.rpm for dist in fedora-17-i386 fedora-17-x86_64 ; do mock rebuild -r $dist $srcrpmpath & done
Překlad nějakého balíčku pro vyjmenované distribuce (použity balíčky z repozitáře EPEL):
srcrpmpath=~/rpmbuild/SRPMS/mod_auth_pgsql-2.0.3-2.f17.src.rpm for dist in epel-5-i386 epel-5-x86_64 epel-6-i386 epel-6-x86_64 ; do mock rebuild -r $dist $srcrpmpath & done
Překlad nějakého balíčku pro vyjmenované distribuce (použity balíčky z repozitářů EPEL i MOJEFIRMA):
srcrpmpath=~/rpmbuild/SRPMS/mod_auth_pgsql-2.0.3-2.f17.src.rpm for dist in mojefirma-epel-5-i386 mojefirma-epel-5-x86_64 mojefirma-epel-6-i386 mojefirma-epel-6-x86_64 ; do mock rebuild -r $dist $srcrpmpath & done
Sledování průběhu buildu
Je vhodné použít nástroj multitail:
sudo yum -y install multitail
Například:
multitail ${MOCKBASEDIR}/epel-5-*/result/*.log multitail ${MOCKBASEDIR}/epel-6-*/result/*.log
Aktualizace repozitáře
GPG podpis
Po úspěšném sestavení balíčku je nutné ho podepsat pomocí gpg. Aby se nepodepisovaly všechny již vytvořené balíky ale pouze ty vyžadované, zadáme si masku. Zde vypisuji všechny varianty, při práci si vyberu jeden řádek metodou 'copy/paste', podobně to bude uváděno i dále:
REPONAMEPATTERN="epel" REPONAMEPATTERN="epel-5" REPONAMEPATTERN="epel-6" REPONAMEPATTERN="mojefirma-epel" REPONAMEPATTERN="mojefirma-epel-5" REPONAMEPATTERN="mojefirma-epel-6"
Podpis všech balíčků ručně. Zde je nutné heslovou frázi na výzvu napsat:
RPMS_TO_SIGN=$(find ${MOCKBASEDIR}/${REPONAMEPATTERN}*/result/ -name '*.rpm' | tr '\n' ' ' ) rpmsign --addsign $RPMS_TO_SIGN
Pro následující skript budeme muset doinstalovat expect:
sudo yum -y install expect
Abych nemusel "heslovou frázi" při podpisování balíčků stále psát, mám ji uloženou v proměnné. Její nastavení provedu takto (mezera na začátku řádku zajistí, že se to neobjeví v bash historii, viz man bash HISTCONTROL=ignoreboth):
PASSPHRASE="nejake fakt dlouhe heslo"
Podpis všech balíčků skriptem:
RPMS_TO_SIGN=$(find ${MOCKBASEDIR}/${REPONAMEPATTERN}*/result/ -name '*.rpm' | tr '\n' ' ' ) export LANG=cs_CZ.UTF-8 if [ -n "$PASSPHRASE" ] ; then /usr/bin/expect -f - << EOF spawn rpmsign --addsign $RPMS_TO_SIGN match_max 100000 fork expect "Vložte heslovou frázi: " send -- "${PASSPHRASE}\r" expect eof EOF else echo "Set PASSPHRASE variable first" fi
Přesun do lokálního repozitáře
Výsledek musíme přesunout na jiné místo, protože to bude při dalším překladu "vyčištěno":
unset REPONAMEPATTERN REPONAMEPATTERN="fedora" REPONAMEPATTERN="centos" REPONAMEPATTERN="epel" REPONAMEPATTERN="mojefirma-epel" BUILDTYPE="os" BUILDTYPE="updates" BUILDTYPE="testing" pushd ${MOCKBASEDIR} for mockchroot in $(/bin/ls -d ${REPONAMEPATTERN}*) ; do if [ "${mockchroot%%-*}" == "fedora" ] ; then repodist=fedora else repodist=centos fi distnr="$(echo $mockchroot | sed -e 's/.*-\([^-]\+\)-\([^-]\+\)$/\1/')" arch="$(echo $mockchroot | sed -e 's/.*-\([^-]\+\)-\([^-]\+\)$/\2/')" mv ${MOCKBASEDIR}/$(basename ${mockchroot})/result/*.src.rpm ${REPOBASEDIR}/${repodist}/${distnr}/${BUILDTYPE}/SRPMS mv ${MOCKBASEDIR}/$(basename ${mockchroot})/result/*.rpm ${REPOBASEDIR}/${repodist}/${distnr}/${BUILDTYPE}/${arch}/RPMS done popd
Tvorba repozitáře a přesun na FTP
Aktualizace údajů o balíčcích v repozitáři a přenos na FTP:
CentOS
(createrepo je nutné spouštět na CentOS/RHEL, jinak by to klienti nebyli schopni načíst.)
unset DRYRUN DRYRUN="-n" if [ -n "${REPOBASEDIR}" -a -n "${FTPSERVER}" -a -n "${FTPBASEDIR}" ] ; then rsync -av --delete -e "ssh -l root -p ${FTPSERVERSSH}" ${REPOBASEDIR}/centos/ ${FTPSERVER}:/${FTPBASEDIR}/centos/ \ --exclude headers/ --exclude repodata/ --exclude /kickstarts/ \ ${DRYRUN} else echo "Nastav promenne: REPOBASEDIR, FTPSERVER a FTPBASEDIR" fi
Tvorba souborů pro repozitáře (pouze právě kopírovaných):
ssh -l root -p ${FTPSERVERSSH} ${FTPSERVER} " for distnr in 5 6 ; do for type in $BUILDTYPE ; do for arch in i386 x86_64 SRPMS ; do workingdir=${FTPBASEDIR}/centos/\${distnr}/\${type}/\${arch} if [ -d \${workingdir} ] ; then createrepo \${workingdir} fi done done done "
Tvorba souborů pro repozitáře (všech):
ssh -l root -p ${FTPSERVERSSH} ${FTPSERVER} " for distnr in 5 6 ; do for type in os updates testing ; do for arch in i386 x86_64 SRPMS ; do workingdir=${FTPBASEDIR}/centos/\${distnr}/\${type}/\${arch} if [ -d \${workingdir} ] ; then createrepo \${workingdir} fi done done done "
Poslat na zrcadlená FTP:
ssh -l root -p ${FTPSERVERSSH} ${FTPSERVER} "for FTPSERVERMIRROR in ${FTPSERVERMIRRORS} ; do /usr/bin/rsync -av -e 'ssh -p ${FTPSERVERSSH}' --delete ${FTPBASEDIR}/ \${FTPSERVERMIRROR}:${FTPBASEDIR}/ ; done"
Fedora
Tvorba souborů pro repozitáře (pouze právě kopírovaných):
for distnr in 17 18 ; do for type in $BUILDTYPE ; do for arch in i386 x86_64 SRPMS ; do workingdir=${REPOBASEDIR}/fedora/${distnr}/${type}/${arch} if [ -d ${workingdir} ] ; then createrepo ${workingdir} fi done done done
Tvorba souborů pro repozitáře (všech):
for distnr in 17 18 ; do for type in os updates testing ; do for arch in i386 x86_64 SRPMS ; do workingdir=${REPOBASEDIR}/fedora/${distnr}/${type}/${arch} if [ -d ${workingdir} ] ; then createrepo ${workingdir} fi done done done
Poslat na zrcadlené FTP:
unset DRYRUN DRYRUN="-n" if [ -n "${REPOBASEDIR}" -a -n "${FTPSERVER}" -a -n "${FTPBASEDIR}" ] ; then rsync -av --delete -e "ssh -l root -p ${FTPSERVERSSH}" ${REPOBASEDIR}/fedora/ ${FTPSERVER}:/${FTPBASEDIR}/fedora/ \ ${DRYRUN} else echo "Nastav promenne: REPOBASEDIR, FTPSERVER a FTPBASEDIR" fi
Další užitečné příkazy
Vypsání všech balíčků v repozitářích:
for dist in centos ; do for distnr in 5 6 ; do for buildtype in os updates testing ; do echo -e "\nREPO ${REPOBASEDIR}/${dist}/${distnr}/${buildtype}/SRPMS: " ls ${REPOBASEDIR}/${dist}/${distnr}/${buildtype}/SRPMS for arch in i386 x86_64 ; do echo -e "\nREPO ${REPOBASEDIR}/${dist}/${distnr}/${buildtype}/${arch}/RPMS: " ls ${REPOBASEDIR}/${dist}/${distnr}/${buildtype}/${arch}/RPMS done done done done
Podepsání všech balíčků v repozitářích:
find ${REPOBASEDIR}/centos/ -name '*.rpm' -print0 | xargs -0 rpm --resign
Ukázka práce s GPG podpisy
Vypsání seznamu importovaných GPG klíčů:
rpm -qa gpg-pubkey*
Vypsání podrobnějšího přehledu o importovaných GPG klíčích:
for gpg in $(rpm -qa gpg-pubkey*) ; do rpm -qi $gpg ; done | grep '^Version \|^Summary '
Vypsání podrobností o všech importovaných GPG klíčích:
for gpg in $(rpm -qa gpg-pubkey*) ; do rpm -qi $gpg ; done | less
Ladění při překladu problematického balíčku
Pokud se překlad nedaří, je nutné ho nějak ladit. K tomu lze s výhodou využít mock s volbou --shell.
Vytvoření src.rpm (varianta rpmbuild-md5 je nutná pro EPEL5):
cd ~/rpmbuild/SPECS rpmbuild-md5 -bs cherokee.spec
Ruční překlad pomocí prostředí mock (Fedora)
Smazání prostředí mock:
mock --root=fedora-17-x86_64 --clean
Inicializace prostředí mock:
mock --root=fedora-17-x86_64 --init
Instalace závislostí balíku:
mock --root=fedora-17-x86_64 --installdeps /home/$MYMOCKUSER/rpmbuild/SRPMS/cherokee-0.99.43-1.fc17.src.rpm
Dodatečná instalace vhodných balíků:
mock --root=fedora-17-x86_64 --install vim-enhanced mc
Kopírování src.rpm:
mock --root=fedora-17-x86_64 --copyin /home/$MYMOCKUSER/rpmbuild/SRPMS/cherokee-0.99.43-1.fc17.src.rpm /builddir/build/SRPMS/
Skok do shellu:
mock --root=fedora-17-x86_64 --shell rpm -ivh /builddir/build/SRPMS/cherokee-0.99.43-1.fc17.src.rpm rpmbuild --nodeps -ba /builddir/build/SPECS/cherokee.spec
Editace .spec:
vim /builddir/build/SPECS/cherokee.spec
Příklad ručního překladu pomocí prostředí mock (CentOS/EPEL)
Vše najednou:
rpmbuild-md5 -bs gdal-1.7.1.spec mock --root=mojefirma-epel-5-x86_64 --clean mock --root=mojefirma-epel-5-x86_64 --init mock --root=mojefirma-epel-5-x86_64 --installdeps /home/$MYMOCKUSER/rpmbuild/SRPMS/gdal-1.7.1-1.fc17.src.rpm mock --root=mojefirma-epel-5-x86_64 --install vim mc mock --root=mojefirma-epel-5-x86_64 --copyin /home/$MYMOCKUSER/rpmbuild/SRPMS/gdal-1.7.1-1.fc17.src.rpm /builddir/build/SRPMS/ mock --root=mojefirma-epel-5-x86_64 --shell rpm -ivh /builddir/build/SRPMS/gdal-1.7.1-1.fc17.src.rpm rpmbuild -ba --nodeps /builddir/build/SPECS/gdal-1.7.1.spec mock --root=mojefirma-epel-5-i386 --clean mock --root=mojefirma-epel-5-i386 --init mock --root=mojefirma-epel-5-i386 --installdeps /home/$MYMOCKUSER/rpmbuild/SRPMS/gdal-1.7.1-1.fc17.src.rpm mock --root=mojefirma-epel-5-i386 --install vim-common vim-enhanced mc mock --root=mojefirma-epel-5-i386 --copyin /home/$MYMOCKUSER/rpmbuild/SRPMS/gdal-1.7.1-1.fc17.src.rpm /builddir/build/SRPMS/ mock --root=mojefirma-epel-5-i386 --shell rpm -ivh /builddir/build/SRPMS/gdal-1.7.1-1.fc17.src.rpm rpmbuild -ba --nodeps /builddir/build/SPECS/gdal-1.7.1.spec
13. 5. 2013 at 12:00
Na Fedora.cz sa cim dalej tym viac daju najst naozaj hodnotne clanky, tento je tomu krasny priklad. Len tak dalej ! (do buducna mozno aj nieco o Koji pripadne podrobnejsie o spec resp. rpm). Vdaka a len tak dalej !
14. 5. 2013 at 11:40
Co je to za šílenost ? (ještě že máme DEB)
14. 5. 2013 at 14:54
Hodně těch kroků lze automatizovat a jak sám autor říká, je to hlavně pro případy, kdy člověk nemůže použít nějaký již existující build systém. Nemyslím si, že by RPM bylo nějak obtížnější než DEB, pokud se tedy DEB nějak výrazně nezjednodušil. Naposledy jsem ho viděl před cca 4-5 lety.
14. 5. 2013 at 18:28
Také to upřesním. Po této šílenosti budete mít připravenou výrobní linku pro vlastní RPM repositář, pro 4 různé distribuce v různých architekturách. Docela by mě zajímalo, jak by se to udělalo pro debian/ubuntu. Můžete se o to také podělit.
7. 6. 2013 at 16:16
Autorovi patrí naozaj vďaka za prepracovaný popis. Jiří Eischmann: áno, .deb inštalátor prešiel naozaj ´´veľkými zmenami´´ 🙂 … Osobne si myslím že nováčik v linuxu hľadá niečo tak jednoduchého ako vo windowsoch, klik a install čo je trochu aj zádrhel Linuxu vo všeobecnosti. Príklad: za bežnú vec v systéme považuje prehrávanie filmov, ako si ale naištaluje kodeky? … vo windowse stačilo stiahnúť trebárs win7 codecs 4.1.5, klikol a inštaloval, hned po dokončení mohol filmy pozerať, v linuxu to žiaľ tak nefunguje a aj ked sa ho systém pýta na dodatočné inštalovanie príslušných kodekov a on potvrdí súhlas vyhodí mu hláška že mu chýba repozitár a on je stratený lebo nevie že treba pridať nejaký GPG kľúč RPM fusion a nakoniec mu dôjde trpezlivosť a príkazovej riadke ani nehovorím, keď zbadá koľko príkazov musí tlačiť a on sám neviem kam, než je na druhom riadku v čítaní od zúfalstva zatvorí celý článok a všade každému hovorí ako komplikovaný linux je. Mne osobne tieto veci nerobia najmenší problém aj preto, lebo s distribúciami pracujem už vyše 10 rokov ale snažím sa pochopiť aj začiatočníckú komunitu, ktorá prechádza z platformy windows na linux. Ruku na srdce keď si spomeniem na moje začiatky, nezávidím im to. Preto si myslím aby sa tieto veci pre túto kategoriu užívateľov riešili v jednoduchom GUI a prevedení a hneď budú mať na problematiku iný názor 🙂
5. 5. 2014 at 18:12
Myslím, že tento článek není určen pro „nováčiky v linuxu“. Toto je pro toho, kdo chce překládat balíky ve fedoře, a to ještě pro různé jiné verze, multilib atp.
Jinak k tomu, co zmiňujete, mi nepřijde, že by ta situace byla dnes stále tak špatná. Jediné, co je třeba se naučit, je správně zadat problém do googlu. Když nainstaluji ubuntu (platí to ale i o fedoře a debianu, též Arch má docela dobře dělanou dokumentaci) a potřebuju kodeky nebo něco, stačí v drtivé většině případů dát do google klíčové slovo „ubuntu“ a problém. Vyskočí hned nějaká wiki, kde jsou příkazy (to je fajn, neboť je lze zkopírovat a vložit do terminálu), i se sudo, repozitáři a vším, takže C-c C-v, zadat heslo do sudo a je to.
Samozřejmě, že jsou problémy, které nejsou tak snadné, ale velká část toho běžného, co je potřeba rozchodit, je dobře dokumentovaná.
Navíc se zapomíná na to, že mizí jiné problémy, které je třeba řešit na Windows. Trialverze, ovladače (3G modem například), všelijaký dotěrný software, co se má tendenci přiinstalovat během instalace něčeho chtěného atd.
Linux byl parketou geeků, byl user-unfriendly pro běžné uživatele, leč dnes už to není pravda. Nějvětší problém, se kterým se na tomto poli setkávám, je pověst linuxu, jako něčeho složitého a neznámého, z čeho mají lidi strach a proto to ani nezkusí.
7. 6. 2013 at 16:18
Prepáčte za preklepy, proste sa mi to občas stáva hlavne keď sa ponáhľam 🙂
9. 6. 2013 at 18:23
tak to klobouček, pane autore !