08.29
W pracy admina po jakimś czasie chyba każdy zbiera sobie kolekcję skryptów i programów które używa do debugowania błędów, czy do automatyzacji czynności. Od tooli typu nmap, socat czy tcpdump które są niesamowicie użyteczne ale nie są instalowane w domyślnej instalacji, po własne skrypty automatyzujące niektóre czynności, czy służące np. do wyciągania statów z monitoringu.
I o ile gdy się ma jeden serwer panowanie na tym nie stanowi wielkiego problemu (zainstalować to co potrzeba, a skrypty wrzucić do /usr/local/bin) to już przy dwóch zaczyna się “aaa mam nową wersję tego skryptu na innym serwerze” a przy większej ilości zwykle kończy się na instalowaniu tooli “kiedy są potrzebne” czyli za każdym razem tracimy czas, a w przypadku własnych skryptów kończy się to tym że na serwerach jest 6 różnych wersji tego samego skryptu.
Rozwiązanie jest proste, albo trzymać wszystkie skrypty na NFSie ( ale to raczej obejście problemu ), albo zapaczkować je i dodać repo z paczkami do /etc/apt/sources.list. Na szczęście samo tworzenie prostych paczek (bez rzeczy wymaganych żeby paczka była zaakceptowana do “oficjalnego” repo Debiana/Ubuntu) jest dosyć proste. Ale po kolei.
Paczka debianowa “w środku” wygląda mniej-więcej tak:
xani@hydra:~/src/my/pkg-repo/packages/xani-tools (master)ᛯ find . . ./DEBIAN ./DEBIAN/control ./DEBIAN/conffiles ./DEBIAN/postinst ./DEBIAN/prerm ./usr ./usr/bin ./usr/bin/haproxy_stat.pl
Mamy tu katalog DEBIAN gdzie mamy pliki informacyjne paczki oraz skrypty uruchamiane przed/po instalacji/deinstalacji paczki, a pozostałe katalogi to są rzeczy która nasza paczka zainstaluje na dysku (i usunie przy instalacji). Z ważniejszych:
- control – opis/nazwa/wersja paczki oraz zależności (czego wymaga, z czym konfliktuje)
- conffiles – które pliki paczki są plikami konfiguracyjnymi. Plik oznaczony jako “config” w tej paczce, gdy zostanie zmieniony przez usera spowoduje przy nasŧępnej instalacji zapytanie czy zostawić modyfikacje usera czy zainstalować nową wersję configa, a przy usunięciu bez opcji purge config zostanie w systemie
- post/pre inst/rm – wykonywane przed (pre) i po (post) instalacji/usunięciu paczki. Można użyć np. do sprzątania po aplikacji (pliki cache itp.) przy deinstalacji, lub do np. startu aplikacji od razu po instalacji, czy dodawaniu skryptów startowych
Wymagany jest tylko plik control, reszta jest opcjonalna. A wygląda on tak:
Package: xani-tools Version: 0.0.1 Section: base Priority: optional Architecture: all Maintainer: XANi <some@email> Depends: etckeeper (>= 0.40), syslog-ng, emacs23-nox, emacs-goodies-el, git-core, iotop, iftop, links, mc, multitail, mtr-tiny, nmap, psmisc, screen, tcpdump, curl, socat Recommends: swaks, atop, ntpdate Suggests: hping3 Conflicts: rsyslog Description: Some random tools tools i use for everyday work
Po kolei:
- Package/version/section/priority/architecture/maintainer – wiadomo o co chodzi
- Depends: rzeczy bez których paczka się nie zainstaluje
- Recommends: te pakiety zostaną zaznaczone jeżeli nie będą konfliktować z niczym, ale można je odznaczyć i paczka się zainstaluje (nie są wymagane)
- Suggests – oznacza że domyśnie nie zainstaluje danej paczki ale będzie ona na liście sugestii w menadżerze paczek
- Conflicts – nie zainstaluje się gdy ta paczka jest w systemie. W powyższym przykładzie syslog-ng jest w depends a rsyslog w conflicts, więc spowoduje to zmianę rsysloga na syslog-ng. Można robić to samo gdy chce się np. domyślnie instalować postfixa zamiast exima
- Description – wiadomo o co chodzi. Można dodać więcej linijek poniżej ale muszą się zaczynać od spacji (jako kontynuacja poprzedniej linijki)
To teraz tworzenie paczki. Instalujemy dpkg-dev fakeroot (NIE FAKEROOT-NG robi zbugowane paczki z ownerem plików jako user a nie root) i:
$ fakeroot dpkg-deb -b xani-tools dpkg-deb: budowanie pakietu "xani-tools" w "xani-tools.deb".
albo gdy chcemy mieć numer wersji w paczce:
$ fakeroot dpkg-deb -b xani-tools ../repo dpkg-deb: budowanie pakietu "xani-tools" w "../repo/xani-tools_0.0.1_all.deb".
I jeżeli chodzi o budowanie najprostrzej paczki to tyle ;]. Ale to nam nie wystarcza, chcemy przecież repo dla naszych serwerów, idealnie z paczkami w gicie, podzielone na część “stabilną” i “dev”. Zacznijmy więc od repo gitowego:
xani@hydra:~/src/my/pkg-repoᛯ find . . ./packages ./packages/xani-tools ./packages/xani-tools/DEBIAN ./packages/xani-tools/DEBIAN/postinst ./packages/xani-tools/DEBIAN/prerm ./packages/xani-tools/DEBIAN/conffiles ./packages/xani-tools/DEBIAN/control ./packages/xani-tools/usr ./packages/xani-tools/usr/bin ./packages/xani-tools/usr/bin/haproxy_stat.pl xani@hydra:~/src/my/pkg-repoᛯ git init Initialized empty Git repository in /home/xani/src/my/pkg-repo/.git/ xani@hydra:~/src/my/pkg-repo (master)ᛯ git add . ; git commit -a -m 'Initial commit' [master (root-commit) 7a0bd78] Initial commit 3 files changed, 48 insertions(+), 0 deletions(-) create mode 100644 packages/xani-tools.deb create mode 100644 packages/xani-tools/DEBIAN/conffiles create mode 100644 packages/xani-tools/DEBIAN/control create mode 100755 packages/xani-tools/DEBIAN/postinst create mode 100755 packages/xani-tools/DEBIAN/prerm create mode 100755 packages/xani-tools/usr/bin/haproxy_stat.pl
I teraz część najważniejsza, mianowicie budowanie paczek. Chcemy mieć możliwość cofnięcia się do starszej wersji paczki, oraz żeby paczki w branchu gitowym dev (i każdym innym) były w oddzielnym repo:
#!/bin/sh
PKGDIR="packages"
TMPDIR="/tmp/repo"
REPODIR="/home/xani/src/my/repo"
STARTPWD=$(pwd)
git clone . $TMPDIR
if [ $1 ] ; then
BRANCH=$1
else
BRANCH="master"
fi
#make sure repodir exists
mkdir -p $REPODIR/$BRANCH/binary
cd $TMPDIR
git checkout $BRANCH
cd $PKGDIR
for a in $(find . -mindepth 1 -maxdepth 1 -type d) ;do
fakeroot dpkg-deb -b $a $REPODIR/$BRANCH/binary
done
# cleaning
rm -rf $TMPDIR
#making Packages.gz
cd $REPODIR/$BRANCH
dpkg-scanpackages -m binary /dev/null | gzip -9c > Packages.gz
czyli gdy odpalimy ten skrypt w katalogu głównym repa stworzy on nam repo w podanym katalogu z brancha master, chyba że podamy mu nazwę innego brancha. Teraz wystarczy dodać do repo docelowego serwera coś w stylu:
deb ssh://repo@reposerwer/repo/packages/master ./
i dodać klucze publiczne. Można także po prostu udostępnić przez http jak “normalne” repo, wszystko zależy czy w naszych paczkach jest coś poufnego.
Dalszy rozwoj to budowanie paczek w posthookach repo albo używając hooków githuba (aktualnie mam tak w pracy, minutę-dwie po commicie przychodzi mi email z wynikami budowania paczek i ew. błędami).
Na początku to trochę roboty ale szybko się zwraca, zwłaszcza gdy już zrobi się parę paczek typu “zainstaluj mi wszystko co jest wymagane do postawienia LAMP” albo “zainstaluj mi toole które używam” :)


5 ResponsesLeave a comment ?
Przydają się tego typu artykuły, pokazujące że nie święci garnki lepią :)
Co do rozwiązania oryginalnego problemu (dystrybucja “niezbędnych” pakietów), zwłaszcza w kontrolowanym dużym środowisku, to lepiej sprawdza się cfengine/puppet – niezależnie od faktu czy skrypty mamy spakowane w pakiet czy nie.
Generalnie tak, ale repo własnych paczek i tak warto mieć dla “homemade” tooli. Tak samo do dystybuowania configów, można ofc zrobić paczkę która by konfigurowała np. apacha według potrzeb, ale zwykle lepiej używać jakiegoś systemu typu cfengine. Zależy od skali ;].
Tak naprawdę nie musiałbyś paczkować konfigów startowych, gdyby Debian miał rozsądny system seryjnej, nienadzorowanej instalacji :> Ale może już za (debianowe) pół roku ;)))))))
szczerze mówiąc nigdy nie potrzebowałem bo większość instalacji to wirtualki, przywrócenie z gotowego obrazu jest dużo szybsze niż jakakolwiek unattended install. Poza tym i tak potrzebujesz paczek jeżeli chcesz dorzucić jakiś własny skrypt.
Ale tak, coś takiego jak kickstart byłoby całkiem użyteczne ;p
Jest takie coś (nazwy nie pamiętam), nawet częsciowo kompatybilne z kickstartem (co jest dużym plusem, bo jego składnia wskazuje na to, że ktoś długo nad nią myślał ;)). Darowałem sobie dalsze poznawanie w momencie, gdy stwierdziłem że mogę utworzyć PV, ale nie mogę na PV utworzyć VG, LV i pozakładać fs-ów na nich ;))