Ręczne składanie pakietów
Ostatnia zmiana: 2025-07-06 12:47

W systemie OpenWrt do wydania 24.10 włącznie używany był program opkg do zarządzana pakietami. Jest on forkiem starszego programu ipkg i wykorzystuje pliki z rozszerzeniem *.ipk. Technicznie rzecz biorąc, plik ipk jest prostym archiwum plików i innych archiwów. Pakiety ipk tworzone są przez SDK OpenWrt z odpowiednich plików Makefile, ale nic nie stoi na przeszkodzie żeby taki pakiet stworzyć ręcznie, nawet w samym systemie OpenWrt.

Na pakiet ipk składają się trzy rzeczy:
- plik o nazwie debian-binary zawierający informację o wersji formatu (jest to ciąg znaków "2.0" zakończony znakiem nowej linii)
- plik będący archiwum w formacie tar.gz o nazwie data.tar.gz zawierający spakowane pliki stanowiące zawartość pakietu
- plik będący archiwum w formacie tar.gz o nazwie control.tar.gz zawierający pliki opisujące czym jest zawartość pakietu

Zróbmy więc swój własny pakiet ipk wykorzystując do tego OpenWrt (choć oczywiście można to też zrobić w normalnym linuksie).

Przygotowania

Tworzymy katalog gdzie będziemy wszystko składać. Logujemy się do jakiegoś urządzenia z OpenWrt i robimy:


    # mkdir -p /tmp/pakiet
    # cd /tmp/pakiet

Wszystko będzie umieszczone w tym katalogu, więc przechodzimy do niego; wszystkie poniższe polecenia wykonujemy już w tym katalogu. Tam też powstanie wynikowy plik *.ipk

debian-binary

To zwykły plik tekstowy, więc jego stworzenie jest proste:


    # echo "2.0" > debian-binary

data.tar.gz

To archiwum z plikami które chcemy spakietować. Pliki muszą być już skompilowane, przygotowane w formie nadającej się do bezpośredniego uruchomienia w OpenWrt, z odpowiednimi bibliotekami oraz z odpowiednimi uprawieniami. Wszystkie pliki będą instalowane względem katalogu głównego (root - /).


    # mkdir -p files

Do katalogu files należy skopiować pliki które mają znaleźć się w pakiecie, umieszczone już we właściwych podkatalogach.
Dla testów zróbmy jeden plik będący skryptem wykonywalnym, umieszczonym docelowo w katalogu /usr/bin pod nazwą witaj-swiecie.sh. Plik będzie miał taką zawartość:


    #!/bin/sh
    echo "Witaj swiecie!"
    exit 0

Jeżeli mamy plik przygotowany w edytorze tekstowym to należy zrobić katalogi w files i go tam skopiować. Na potrzeby tego poradnika zróbmy go po prostu ręcznie:


    # mkdir -p files/usr/bin
    # echo '#!/bin/sh' > files/usr/bin/witaj-swiecie.sh
    # echo 'echo "Witaj swiecie!"' >> files/usr/bin/witaj-swiecie.sh
    # echo 'exit 0' >> files/usr/bin/witaj-swiecie.sh

Nie wolno zapominać o uprawnieniach tego pliku


    # chmod 755 files/usr/bin/witaj-swiecie.sh

Tak przygotowaną strukturę katalogową z plikami pakujemy do pliku o nazwie data.tar.gz


    # cd files
    # tar -zcvf ../data.tar.gz .
    # cd ..

W katalogu /tmp/pakiet powinien powstać plik data.tar.gz.

control.tar.gz

To archiwum z kolei zawiera trzy pliki:
- postinst, który zawiera standardowe skrypty wykonujące się po zainstalowaniu pakietu
- prerm, który zawiera standardowe skrypty wykonujące się przed odinstalowaniem pakietu
- control, opisujący sam pakiet
Robimy katalog gdzie w/w pliki będą utworzone:


    # mkdir -p control

Dwa pierwsze pliki muszą mieć określoną zawartość więc wystarczy je zrobić:


    # echo '#!/bin/sh' > control/postinst
    # echo '[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0' >> control/postinst
    # echo '[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0' >> control/postinst
    # echo '. ${IPKG_INSTROOT}/lib/functions.sh' >> control/postinst
    # echo 'default_postinst $0 $@' >> control/postinst
    # chmod 755 control/postinst

    # echo '#!/bin/sh' > control/prerm
    # echo '[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0' >> control/prerm
    # echo '. ${IPKG_INSTROOT}/lib/functions.sh' >> control/prerm
    # echo 'default_prerm $0 $@' >> control/prerm
    # chmod 755 control/prerm

Te pliki to zawartość domyślna z OpenWrt, które nie zawierają skryptów specyficznych dla pakietu uruchamianych po instalacji i przed usunięciem.

Zostaje do utworzenia sam plik control. Jego dość prosta zawartość wygląda następująco:


    Package: <nazwa pakietu>
    Version: <pełna wersja z ew numerem rewizji>
    Depends: libc <i inne zależności>
    Source: <źródło pakietu>
    SourceName: <źródło pakietu>
    Section: <sekcja do której należy pakiet>
    SourceDateEpoch: <znacznik czasowy utworzenia pakietu>
    Maintainer: <opiekun pakietu>
    Architecture: all <all - dla wszystkich architektur albo określona nazwa jeżeli w pakiecie mają znaleźć się binarki>
    Installed-Size: <rozmiar po instalacji>
    Description: <opis pakietu>

Taki plik znów można przygotować w edytorze tekstowym lub zrobić go przy pomocy echo. Posłużymy się tą drugą metodą:


    # echo 'Package: helloworld' > control/control
    # echo 'Version: 20250705-r1' >> control/control
    # echo 'Depends: libc' >> control/control
    # echo 'Source: helloworld' >> control/control
    # echo 'SourceName: helloworld' >> control/control
    # echo 'Section: utils' >> control/control
    # echo 'SourceDateEpoch: '$(date +%s) >> control/control
    # echo 'Maintainer: Jan Kowalski <user@foo.org>' >> control/control
    # echo 'Architecture: all' >> control/control
    # echo 'Installed-Size: '$(du -kcs files | awk '/total/{print $1*1024}') >> control/control
    # echo 'Description: Witaj swiecie' >> control/control

Polecenie du -kcs files wyświetla zajętość katalogu files, czyli mniej-więcej ile pakiet zajmuje po instalacji, awk służy to przeliczenia tego na bajty. Można teraz wykonać polecenie


    # ls -al control

aby sprawdzić czy mamy wszystkie pliki. Wynik powinien wyglądać podobnie do tego:


    drwxr-xr-x 2 root root 100 Jul 5 08:32 .
    drwxr-xr-x 4 root root 120 Jul 5 08:20 ..
    -rw-r--r-- 1 root root 241 Jul 5 08:33 control
    -rwxr-xr-x 1 root root 160 Jul 5 08:20 postinst
    -rwxr-xr-x 1 root root 117 Jul 5 08:20 prerm

Pakujemy to:


    # cd control
    # tar -zcvf ../control.tar.gz .
    # cd ..

Tworzenie pakietu

W rezultacie w katalogu /tmp/pakiet powinny znajdować się teraz wszystkie niezbędne pliki:


    # ls -la
    drwxr-xr-x 4 root root 140 Jul 5 08:36 .
    drwxrwxrwt 18 root root 520 Jul 5 08:33 ..
    drwxr-xr-x 2 root root 100 Jul 5 08:32 control
    -rw-r--r-- 1 root root 467 Jul 5 08:36 control.tar.gz
    -rw-r--r-- 1 root root 208 Jul 5 08:12 data.tar.gz
    -rw-r--r-- 1 root root 4 Jul 5 08:01 debian-binary
    drwxr-xr-x 4 root root 80 Jul 5 08:16 files

Jeżeli tak jest to robimy pakiet:


    # tar -zcvf helloworld_20250705-r1.ipk control.tar.gz data.tar.gz debian-binary

Gdzie nazwa pliku powinna być w formacie "nazwa pakietu" podkreślenie "numer wersji" ipk. Choć to sprawa umowna bo plik może nazywać się też "alamakota.ipk" i też powinno być dobrze.
Sprawdźmy czy plik jest


    # ls -la *.ipk
    -rw-r--r-- 1 root root 882 Jul 5 08:38 helloworld_20250705-r1.ipk

Sprawdźmy czy da się go zainstalować i czy działa:


    # opkg install ./helloworld_20250705-r1.ipk
    Installing helloworld (2025-07-05-r1) to root...
    Configuring helloworld.

    # opkg list-installed | grep helloworld
    helloworld - 2025-07-05-r1

    # opkg files helloworld
    Package helloworld (2025-07-05-r1) is installed on root and has the following files:
    /usr/bin/witaj-swiecie.sh

    # opkg info helloworld
    Package: helloworld
    Version: 2025-07-05-r1
    Depends: libc
    Status: install user installed
    Architecture: all
    Installed-Time: 1751697614

    # ls /usr/bin/witaj-swiecie.sh
    /usr/bin/witaj-swiecie.sh

    # witaj-swiecie.sh
    Witaj swiecie!


W praktyce w/w polecenia można łatwo oskryptować i robić pakiety prawie że automatycznie.

Zakończenie

Należy jeszcze wspomnieć do dwóch oczywistych rzeczach:
- gotowy pakiet ipk można rozpakować - ponieważ jest to archiwum
- zainstalowany pakiet ipk w systemie OpenWrt można wydobyć i zgromadzić wszystkie pliki. Przy odrobinie wytrwałości można z tych plików znów złożyć gotowy pakiet przeznaczony do ponownej instalacji