Il est possible de fournir des scripts qui seront exécutés par le système de gestion de paquet lors d'une installation, d'une mise à jour ou d'une suppression du paquet.
Ces scripts sont les fichiers preinst
, postinst
,
prerm
et postrm
contenus dans le répertoire de
contrôle du paquet. Ils doivent être des fichiers exécutables corrects ;
quand ce sont des scripts (ce qui est recommandé), ils doivent commencer par la
convention habituelle : #!. Ils seront lisibles et exécutables
par tout le monde mais ils ne pourront pas être modifiés par tout le monde.
Le système de gestion de paquet teste le code de sortie de ces scripts. Il est important que ce code soit différent de zéro quand il y a une erreur ; le système de gestion de paquet peut alors s'interrompre. Pour les scripts shell, cela signifie qu'on doit presque toujours utiliser set -e (et c'est généralement vrai pour tout script shell). Bien sûr, il est aussi important que ce code ne soit pas différent de zéro quand tout s'est bien passé.
Quand un paquet est mis à jour, une combinaison des scripts de l'ancien et du nouveau paquet est appelée durant la procédure de mise à jour. Il faut faire attention quand les scripts se compliquent et il faut vérifier leurs arguments.
D'une manière générale, le script preinst
est appelé avant
d'installer (une version particulière d') un paquet, et le script
postinst
après ; le script prerm
avant d'effacer
(une version d') un paquet et postrm
après.
Normalement on ne doit pas préfixer le chemin des programmes appelés par les
scripts. Avant le début de l'installation, le système de gestion de paquet
vérifie que les programmes ldconfig
,
start-stop-daemon
, install-info
et
update-rc.d
peuvent être trouvés via la variable d'environnement
PATH. Ces programmes, et n'importe quel autre programme qu'on
s'attend à trouver dans le PATH, seront donc appelés sans nom de
chemin absolu. Les scripts du responsable ne doivent pas non plus
réinitialiser la variable PATH, bien qu'ils puissent choisir de la
modifier en ajoutant au début ou à la fin un répertoire spécifique à un paquet.
Ces considérations s'appliquent vraiment à tous les scripts shell.
Il est nécessaire pour les procédures de gestion des erreurs que les scripts soient idempotents. Cela signifie qu'un script, appelé à nouveau après une exécution réussie, n'explose pas et ne fait pas de dégâts ; il s'assure simplement que chaque chose est à sa place. Si le premier appel échoue, ou s'arrête au milieu du chemin pour une raison ou une autre, le second appel fera, s'il y en a, les choses qui n'ont pas été faites la première fois et se terminera normalement si tout est correct [36].
Les scripts du responsable sont assurés de s'exécuter avec un terminal de
contrôle et de pouvoir interagir avec l'utilisateur. Quand ils ont besoin de
demander un mot de passe, d'intervenir en plein écran... c'est à partir de et
vers /dev/tty qu'ils le feront, puisque dpkg
redirige
à un moment ou un autre les sorties et entrées standard des scripts de manière
à enregistrer le processus d'installation. De même les scripts Perl, ces
scripts pouvant rediriger leur sortie standard dans un tube à des fins
d'enregistrement, utiliseront un mode de sortie sans tampon mémoire en
déclarant $|=1 de manière à ce que la sortie soit affichée
immédiatement plutôt que d'être mise dans un tampon mémoire.
Chaque script retournera un code de sortie égal à zéro en cas de succès et un code différent de zéro en cas d'échec.
La procédure lors d'une installation, d'une mise à jour, d'un remplacement ou d'une disparition (c'est-à-dire quand on exécute dpkg --unpack, ou bien l'étape unpack de dpkg --install) est la suivante. Dans chaque cas, si une erreur majeure se produit (à moins d'être listée ci-dessous), les actions sont généralement « rembobinées » -- ce qui signifie que les scripts du responsable sont exécutés dans l'ordre inverse avec des arguments différents. Ce sont les appels « correction d'erreur » listés ci-dessous.
prerm-de-l'ancien-paquet upgrade nouvelle-version
dpkg
essaye :
prerm-du-nouveau-paquet failed-upgrade vieille-version
Correction d'erreur, dans les deux cas ci-dessus :
postinst-de l'ancien-paquet abort-upgrade nouvelle-version
prerm-du-paquet-déconfiguré deconfigure in-favour paquet-à-installer version removing paquet-conflictuel version
Correction d'erreurs :
postinst-du- paquet-déconfiguré abort-deconfigure in-favour paquet-dont-l'installation-a-échouée version removing paquet-conflictuel version
Les paquets déconfigurés sont indiqués comme nécessitant une configuration, afin que si l'option --install est utilisée, ils soient, si possible, de nouveau configurés.
prerm-du-paquet-conflictuel remove in-favour paquet nouvelle-version
Correction d'erreurs :
postinst-du-paquet-conflictuel abort-remove in-favour paquet nouvelle-version
preinst-du-nouveau-paquet upgrade vieille-version
preinst-du-nouveau-paquet install vieille-version
preinst-du-nouveau-paquet install
Les corrections d'erreurs, respectivement :
postrm-du-nouveau-paquet abort-upgrade vieille-version postrm-du-nouveau-paquet abort-install vieille-version postrm-du-nouveau-paquet abort-install
C'est une erreur pour un paquet de contenir des fichiers qui sont sur le système dans un autre paquet, à moins que Replaces soit utilisé (voir le champ Replaces -- regénérer les fichiers et remplacer les paquets, Section 7.5).
C'est une erreur plus grave pour un paquet de contenir un simple fichier ou autre chose qu'un répertoire quand un autre paquet veut un répertoire (à moins que Replaces ne soit utilisé). Cette erreur peut être évitée si c'est l'effet recherché, en utilisant --force-overwrite-dir, mais ce n'est pas à conseiller.
Les paquets qui remplacent mutuellement leurs fichiers ont une démarche qui, bien que déterministe, est difficile à comprendre pour un administrateur système. Cela peut aisément conduire à des programmes annoncés comme « absent » quand, par exemple, un paquet remplaçant tel fichier d'un autre paquet est installé puis effacé [37].
Un répertoire ne sera jamais remplacé par un lien symbolique vers un répertoire
et vice versa ; à la place, l'état existant (lien symbolique ou non) est
conservé et dpkg
suivra les liens s'il y en a.
postrm-de l'ancien-paquet upgrade nouvelle-version
dpkg
essaye :
postrm-du-nouveau-paquet failed-upgrade vieille-version
Les corrections d'erreur, dans les deux cas :
preinst-de-l'ancien-paquet abort-upgrade nouvelle-version
dpkg
atteint ce point, il ne
revient pas en arrière si une erreur se produit. Le paquet reste dans un très
mauvais état et demande une réinstallation réussie pour remettre tout en place
; cela arrive quand dpkg
commence à faire des choses
irréversibles.
dpkg
appelle:
postrm-du-paquet-effacé disappear remplaçant version-du-remplaçant
dpkg
). Il faut remarquer que
dpkg
n'appelle pas le script prerm du paquet effacé, car il ne
sait pas à l'avance que le paquet va disparaître.
C'est un autre point de non-retour - si l'effacement d'un paquet conflictuel échoue, on ne « rembobine » pas le reste de l'installation ; le paquet conflictuel est laissé dans un état « enlevé à moitié ».
Quand on configure un paquet (avec dpkg --install, ou avec --configure), on met à jour d'abord les conffiles et ensuite on appelle :
postinst configure version-la-plus-récemment-configurée
On n'essaye pas de « rembobiner » après une erreur pendant la configuration.
S'il n'existe pas de « version-la-plus-récemment-configurée »,
dpkg
passe un argument nul ; les vieilles versions de
dpkg
peuvent passer dans ce cas <unknown> (avec
les signes supérieur et inférieur). Et les plus vieilles versions ne passent
pas de second argument du tout, quelques soient les circonstances.
prerm remove
postrm remove
postrm
.
Si on n'efface pas le paquet, la procédure s'arrête là. Il faut remarquer que
les paquets qui n'ont pas de postrm
ni de conffiles
sont automatiquement purgés pendant l'effacement, puisqu'il n'y pas de
différence, sauf pour le fichier status de dpkg
.
postrm purge
Aucune tentative n'est faite pour « rembobiner » après une erreur durant la phase de suppression.
La Charte Debian
version 3.6.0.0 Juillet 2003