Dans le cadre du déploiement d’une application, on a souvent besoin de réaliser un programme d’installation de celle-ci. Une solution possible est de créer un paquet.
Un paquet ou parfois paquetage (package) est une archive (souvent compressée) comprenant les fichiers, les informations et procédures nécessaires à l’installation d’un logiciel sur un système d’exploitation en s’assurant de la cohérence fonctionnelle du système ainsi modifié. L’utilisation d’un paquetage logiciel est un élément constitutif d’une bonne pratique d’intégration logicielle.
Les types de paquets les plus répandus sous Linux sont :
deb est le format de fichier des paquets logiciels de la distribution Debian GNU/Linux. Presque toutes les distributions basées sur Debian utilisent aussi ce format (Ubuntu par exemple).
rpm (Red Hat Package) est un système de gestion de paquets de logiciels utilisé sur certaines distributions GNU/Linux. C’est le format utilisé par Linux Standard Base (LSB).
pacman (contraction de package-manager) est le gestionnaire de paquets officiel de la distribution Linux Arch Linux. Pacman utilise des archives .tar.gz, .bz2 ou .xz pour ses paquets.
Voir aussi : le format tgz (fichier archive créé avec tar
et ensuite compressé généralement avec gzip
), msi (pour les fichiers d’installation pour Windows Installer) …
Lire :
Pour réaliser une procédure d’installation d’une application, il faudra décomposer celle-ci en trois parties :
make
) en édition statique ou dynamiqueCes trois parties sont parfois dépendantes de la plateforme et des outils utilisés.
Voir aussi :
De manière générale, il faut résoudre un certain nombre de problèmes et répondre à quelques choix.
Droits et licence ? Les droits et les fichiers à déployer (consulter le contrat de licence de Qt par exemple) et les droits et les fichiers à appliquer à son application. Lire : www.gnu.org/licenses/.
Statique ou dynamique ? Il faudra choisir entre fabriquer un exécutable indépendant (statique) ou non (dynamique). Sous Linux, les dépendances sont nombreuses : architecture multi-platerforme, bibliothèques, etc … Lire : linux-deployment.html.
Librairies dynamiques ? Les bibliothèques dynamiques contiennent du code exécutable (des fonctions formant une API) qui sera susceptible d’être utilisé par un (ou plusieurs) programmes au moment de leur exécution. En cas de besoin, la librairie dynamique sera chargée en mémoire et son code sera alors utilisable par le programme demandeur. Il en résulte les avantages suivants : la taille du programme est réduite (puisque le code dont il a besoin se trouve dans la librairie), la possibilité de faire évoluer la librairie sans avoir à recompiler (si le prototype des fonctions définies dans la librairie reste inchangé). L’inconvénient majeur reste l’obligation de la présence de la librairie sur le système cible pour que le programme puisse s’exécuter. L’extension usuelle d’une librairie dynamique sous Linux est .so
(pour Windows, ce sera .dll
)
Dépendances ? Il y a plusieurs techniques pour connaître les dépendances externes d’une application : utiliser un utilitaire qui recherche ces dépendances (les commandes ldd
, objdump
, strace
, dpkg
et dpkg-depcheck
par exemple sous Linux) ou appliquer une démarche (rudimentaire !) qui teste l’application sur une machine vierge (une machine virtuelle par exemple) et qui résout les dépendances les unes après les autres.
L’emplacement ? Il faudra déterminer où installer l’application (dans les chemins partagés /usr/bin/
et /usr/local/bin
, séparés dans /opt/
ou dans $HOME
pour Linux). On peut aussi envisager de créer une entrée dans le menu Application de l’environnement de bureau et aussi un raccoruci.
Les fichiers de l’application à déployer ? Il faut évidemment recenser les fichiers (ainsi que l’arborescence) qui composent l’application et qui devront être déployer avec celle-ci. De manière générale, on trouve : l’exécutable, l’icône (.ico
), des fichiers de configuration (comme les .ini
), des fichier multimédia (comme des images), des fichiers d’aide (comme les .chm
ou les pages man
, des fichiers .html
, …), un fichier licence, un fichier readme, etc …
On désire au final regrouper toutes ces actions et tous ces fichiers dans un même et seul fichier : le paquet.
Il faut tout d’abord créer une arborescence qui va permettre ensuite de créer le paquet. Le répertoire racine doit avoir le nom du paquet. Ensuite, il doit y avoir un sous répertoire DEBIAN
contenant certains fichiers :
control
: fichier décrivant les informations relatives au paquetpostinst
: script exécuté après l’installation du paquetpostrm
: script exécuté après la désinstallation du paquetpre*
: les scripts exécutés avant l’installation du paquetRemarques : Tous les fichiers post* et pre* doivent avoir les permissions 755 (rwxr-xr-x
), idem pour les répertoires. Il est également possible de créer d’autres scripts dans le répertoire DEBIAN
.
Le reste du contenu du répertoire racine représente une arborescence debian usuelle. C’est à dire que si on souhaite installer un fichier dans /urs/bin
par exemple, il suffira de créer les sous répertoires usr
et bin
dans le répertoire racine et d’y placer ce qui devra être installé à cet endroit.
Commençons par créer les répertoires de base :
$ cd $HOME
$ mkdir -p qhelloworld/DEBIAN
$ cd qhelloworld
On va ensuite créer les répertoires ci-dessous et ycopier les fichiers suivants :
./usr/
./usr/bin/
./usr/bin/qhelloworld
./usr/share/
./usr/share/doc/
./usr/share/doc/qhelloworld/
./usr/share/doc/qhelloworld/COPYING
./usr/share/doc/qhelloworld/ChangeLog
./usr/share/doc/qhelloworld/AUTHORS
./usr/share/doc/qhelloworld/TODO
./usr/share/doc/qhelloworld/INSTALL
./usr/share/doc/qhelloworld/NEWS
./usr/share/doc/qhelloworld/README
./usr/share/man/
./usr/share/man/man1/
./usr/share/man/man1/qhelloworld.1.lzma
L’aroborescence de l’exemple est ici.
Le fichier DEBIAN/control
permet de décrire le paquet : dépendances, description, nom, auteur et mainteneur du paquet …
Documentation : DEBIAN/control
$ vim $HOME/qhelloworld/DEBIAN/control
Package: qhelloworld
Version: 1.0
Section: base
Priority: optional
Architecture: all
Depends: libc6, libgcc1, libstdc++6, libqtgui4, libqtcore4
Maintainer: Mr Doe <doe@nowhere.com>
Description: une description ...
Remarque : la description du paquet doit obligatoirement être suivie d’un retour à la ligne sinon dpkg-deb
renverra une erreur lors de l’analyse syntaxique.
Une des partie essentielle dans les paquets est la gestion des dépendances (mot-clé Depends). On peut restreindre les dépendances à des versions particulières de chaque paquet nommé. La restriction de chaque paquet particulier est indiquée entre parenthèses après son nom avec une relation (<<, <=, =, >= et >>) suivie par une valeur de numéro de version. Par exemple : Depends: toto (>= 1.2)
Il existe un outil qui permet de lister les dépendances : dpkg-depcheck
. On peut aussi s’aider des commandes ldd
, objdump
, et dpkg
:
$ sudo apt-get install devscripts
$ dpkg-depcheck /$HOME/qhelloworld/usr/bin/qhelloworld
...
Packages used:
libgnome2-0
fonts-tlwg-mono
fontconfig-config
libxdamage1
libpango1.0-0
ttf-indic-fonts-core
libgpg-error0
libpcre3
libx11-6
$ objdump -p /$HOME/qhelloworld/usr/bin/qhelloworld | grep NEEDED
NEEDED libQtGui.so.4
NEEDED libQtCore.so.4
NEEDED libstdc++.so.6
NEEDED libgcc_s.so.1
NEEDED libc.so.6
$ dpkg -S libQtGui.so.4
libqtgui4: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1
$ dpkg -S libQtCore.so.4
libqtcore4: /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8
$ dpkg -S libstdc++.so.6
libstdc++6: /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
$ dpkg -S libgcc_s.so.1
libgcc1: /lib/x86_64-linux-gnu/libgcc_s.so.1
$ dpkg -S libc.so.6
libc6: /lib/x86_64-linux-gnu/libc.so.6
Voir aussi : Gestion de la configuration
Le fichier DEBIAN/postinst
est un script qui sera exécuté à la fin de l’installation du paquet.
On peut y faire par exemple des modifications de droits (chmod
), de propriétaire (chown
) ou des créations de répertoires cachés pour des configurations propres aux utilisateurs :
#!/bin/bash
if [ -f "/usr/bin/qhelloworld" ]
then
chown root:root /usr/bin/qhelloworld
fi
if [ -d "/usr/share/doc/qhelloworld" ]
then
chown root:root /usr/share/doc/qhelloworld/*
fi
if [ -f "/usr/share/man/man1/qhelloworld.1.lzma" ]
then
chown root:root /usr/share/man/man1/qhelloworld.1.lzma
fi
mkdir ~/.qhelloworld
touch ~/.qhelloworld/profile
echo "Hello World !" > ~/.qhelloworld/profile
Le fichier DEBIAN/postrm
est un script qui sera exécuté après la désinstallation. Par exemple :
#!/bin/bash
rm -rf ~/.qhelloworld
Il faut se placer dans le répertoire contenant l’arborescence du paquet puis utiliser la commande dpkg-deb
:
$ cd $HOME
$ ls
qhelloworld
$ dpkg-deb --build qhelloworld
dpkg-deb : construction du paquet « qhelloworld » dans « qhelloworld.deb ».
À moins de préciser --nocheck
, dpkg-deb
lit DEBIAN/control
et l’analyse. Il cherche les erreurs de syntaxe et d’autres problèmes existants, puis il affiche le nom du paquet binaire qu’il construit. dpkg-deb
vérifie aussi les permissions des scripts du responsable et des autres fichiers qu’il trouve dans le répertoire de contrôle DEBIAN
.
Il est possible de visualiser le contenu du paquet :
$ dpkg-deb --contents qhelloworld.deb
drwxrwxr-x tv/tv 0 2017-04-21 06:56 ./
drwxrwxr-x tv/tv 0 2017-04-21 06:57 ./usr/
drwxrwxr-x tv/tv 0 2017-04-21 20:45 ./usr/bin/
-rwxr-xr-x tv/tv 14423 2017-04-21 18:03 ./usr/bin/qhelloworld
drwxr-xr-x tv/tv 0 2017-04-21 06:58 ./usr/share/
drwxrwxr-x tv/tv 0 2017-04-21 06:59 ./usr/share/doc/
drwxrwxr-x tv/tv 0 2017-04-21 07:01 ./usr/share/doc/qhelloworld/
-rw-r--r-- tv/tv 17992 2010-04-17 14:24 ./usr/share/doc/qhelloworld/COPYING
-rw-r--r-- tv/tv 140 2017-04-21 07:01 ./usr/share/doc/qhelloworld/ChangeLog
-rw-r--r-- tv/tv 55 2017-04-21 07:01 ./usr/share/doc/qhelloworld/AUTHORS
-rw-r--r-- tv/tv 30 2017-04-21 06:59 ./usr/share/doc/qhelloworld/TODO
-rw-r--r-- tv/tv 310 2017-04-21 07:00 ./usr/share/doc/qhelloworld/INSTALL
-rw-r--r-- tv/tv 0 2010-04-17 14:24 ./usr/share/doc/qhelloworld/NEWS
-rw-r--r-- tv/tv 20 2017-04-21 07:00 ./usr/share/doc/qhelloworld/README
drwxr-xr-x tv/tv 0 2010-04-17 14:24 ./usr/share/man/
drwxr-xr-x tv/tv 0 2010-04-17 14:24 ./usr/share/man/man1/
-rw-r--r-- tv/tv 489 2010-04-17 14:24 ./usr/share/man/man1/qhelloworld.1.lzma
Et d’obtenir des informations sur le paquet :
$ dpkg-deb -I archives/qhelloworld.deb
nouveau paquet Debian, version 2.0.
taille 14050 octets : archive de contrôle = 569 octets.
328 octets, 8 lignes control
399 octets, 16 lignes * postinst #!/bin/bash
34 octets, 2 lignes * postrm #!/bin/bash
Package: qhelloworld
Version: 1.0
Section: base
Priority: optional
Architecture: all
Depends: libc6, libgcc1, libstdc++6, libqtgui4, libqtcore4
Maintainer: Mr Doe <doe@nowhere.com>
Description: une description ...
Pour installer le paquet, on peut simplement utiliser la commande dpkg
:
$ sudo dpkg -i qhelloworld.deb
$ qhelloworld -v
qhelloworld 1.0
Voir aussi : Comment installer un paquet ?
On peut vérifier l’état du paquet :
$ dpkg-query -s qhelloworld
Package: qhelloworld
Status: install ok installed
Priority: optional
Section: base
Maintainer: Mr Doe <doe@nowhere.com>
Architecture: all
Version: 1.0
Depends: libc6, libgcc1, libstdc++6, libqtgui4, libqtcore4
Description: une description ...
$ dpkg -l | grep qhelloworld
ii qhelloworld 1.0 une description ...
$ dpkg-query -L qhelloworld
/.
/usr
/usr/bin
/usr/bin/qhelloworld
/usr/share
/usr/share/doc
/usr/share/doc/qhelloworld
/usr/share/doc/qhelloworld/COPYING
/usr/share/doc/qhelloworld/ChangeLog
/usr/share/doc/qhelloworld/AUTHORS
/usr/share/doc/qhelloworld/TODO
/usr/share/doc/qhelloworld/INSTALL
/usr/share/doc/qhelloworld/NEWS
/usr/share/doc/qhelloworld/README
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/qhelloworld.1.lzma
Pour désinstaller avec dpkg
, on peut utiliser l’option -r
(remove) qui laisse les fichiers de configuration ou l’option -P
(purge) qui supprtime tout :
$ sudo dpkg -P qhelloworld
Le paquet de l’exemple est ici.
Côté serveur :
$ mkdir -p /var/cache/apt/archives
$ cp *.deb /var/cache/apt/archives
$ dpkg-scanpackages ./ /dev/null | gzip -9c > Packages.gz
$ cp Packages.gz /var/cache/apt/archives
$ ln -s /var/cache/apt/archives /var/www/html/packages
$ vim /etc/httpd/conf/httpd.conf
<Directory /var/www/html/packages>
Options Indexes FollowSymLinks
</Directory>
$ sudo /etc/init.d/httpd restart
Côté client :
$ sudo vim /etc/apt/sources.list
## Depot local intranet
deb http://192.168.52.85/packages ./
$ sudo apt-get update