Les dépendances des projets en shell

et autres

Protocolium a été en parti développé dans le cadre d’un projet de recherche. L’objectif de ce projet de recherche est de questionner certaines pratiques de développement produisant du logiciel peu durable et en proposer d’autres, anciennes ou nouvelles, mieux alignées avec des objectifs de sobriété et de durabilité. Protocolium a été développé sur la base d’intuitions nourissant les pratiques supposément plus sobres et durable. Dans ce document nous explorons les dépendances de protocolium dans l’espoir de mesurer sa capacité à s’adapter à son environnement.

Les dépendances des projets shell

Les difficultés

Certaines piles techniques ont parfois recours à des dépôts centralisés construits pour lister et distribuer de manière cohérente les dépendances disponibles. L’usage de ces dépôts permet d’identifier facilement les dépendances d’un projet donné ainsi que les versions utilisées de ces dépendances. C’est en parti pourquoi le domaine de recherche concerné s’attarde sur des dépôts Java dont les dépendances sont gérées avec Maven.1 Il pourrait en aller de même avec des projets javascript et npm, perl et cpan etc.

En shell il n’existe pas (à ma connaissance) de manière standardisée de lister les dépendances d’un projet. La pratique la plus commune semble être2 celle de lister les noms non standardisés des binaires ou scripts externes utilisés par l’outil, l’interpréteur ou les interpréteurs shell et le ou les systèmes sur lesquels il fonctionne.

Une déclaration “typique” des dépendances pour protocolium pourrait ressembler à :

Cette pratique et l’absence de standard découle de :

  1. l’absence de dépôt unique et centralisé contenant les outils habituellement lancés dans des scripts shell
  2. l’ubiquité réelle ou perçue des outils Unix classiquement utilisés dans des scripts shell. Si un outil est considéré par la personne qui développe comme disponible partout elle sera tentée de ne pas le renseigner dans les dépendances.
  3. la relative uniformisation des système successeurs d’Unix suite à la publication du standard POSIX, notamment sa partie “shell and utilies”.
  4. la domination de Linux et des outils de son user space, notamment les outils GNU bash et coreutils.

En réalité la combinaison des points 2. et 4. et une mauvaise connaissance du point 3. de la part de beaucoup de personnes pratiquant le shell rend la déclaration des dépendances telles que décrites plus haut trop peu informative pour aider à une bonne portabilité entre les systèmes et dans le temps.

Par exemple, il est courant qu’un script utilise des fonctionnalités spécifiques à bash sans pour autant spécifier que le projet dépend de bash. Et pour cause, la domination de bash en tant qu’interpréteur de shell pour un usage interactif en a fait un synonyme de shell. Il est même devenu difficile de trouver du contenu sur internet enseignant le shell POSIX ou faisant la distinction entre les types de shell populaires tellement le contenu à propos de bash est mieux référencé.

Autre exemple, de nombreux scripts utilisent des options spécifiques3 aux versions GNU de certains outils essentiels (grep, sed etc). Par exemple sed -i, permettant l’édition d’un fichier “sur place” sans nécessiter de création et de copie de fichier temporaire est fréquemment utilisé sans pour autant être mentionné dans les dépendances.

Les perspectives d’améliorations

Comme indiqué dans 3. il existe depuis 1988 un standard décrivant les éléments essentiels devant se retrouver dans un système d’exploitation pour permettre son usage et de poursuivre son développement. Ce standard spécifie entre autre des éléments du user space comme le comportement du shell et des utilitaires appelés depuis le shell.

Les systèmes d’exploitation n’ont aucune obligation de s’y conformer mais les succésseurs d’Unix (*BSD, MacOs, Linux etc) le font assez largement. Dans l’ensemble ce standard est une bonne référence pour juger, sans avoir à le tester, de la portabilité d’un logiciel entre les OS et dans le temps. La déclaration des dépendances peut alors indiquer si oui ou non un outil est spécifié dans POSIX et si oui, si l’usage qui en est fait dans le logiciel est y est conforme.

Par exemple seq, bien qu’extrêmement souvent installé sur les système par défaut parce que présent dans les coreutils de GNU, n’est pas posix. Il semble alors raisonnable de le lister dans les dépendances. Dans la même idée sed est POSIX mais pas son option -i. Si l’on fait usage de cette option il conviendrait de le renseigner dans les dépendances. En suivant cette logique la déclaration des dépendances de protocolium pourrait être :

Se référer à la spécification POSIX et aux options utilisées n’y étant pas permet d’une certaine manière de se rapprocher d’une déclaration de dépendances “par API”[^1]. Se faisant on stabilise l’usage de l’outil autour d’un document détaillant bien les options disponibles et leurs comportements.

Si cette stratégie est à peu près viable c’est que POSIX est un standard mi-descriptif mi-prescriptif. Descriptif dans la mesure où l’OpenGroup, l’institution en charge du standard, n’invente rien. Lors d’une demande d’inclusion d’un élément il est attendu, en plus d’une justification du bien fondée de la demande, qu’une revue exhaustive de l’existant dans les systèmes Unix à ce sujet soient fournie. Si la demande d’inclusion est suffisament bien motivée, c’est sur la base de cette revue qu’OpenGroup décidera de la spécification à retenir, généralement le dénominateur commun des outils existants4. Prescriptif puisqu’une fois l’inclusion adoptée les personnes développant des systèmes et utilitaires cherchent très largement à reproduire les options et comportements décrits dans le standard.

Les limites

Malheureusement dire “grep posix” n’est toujours pas suffisamment précis pour permettre de savoir si une version particulière d’un outil sera compatible avec notre outil. Cela pour plusieurs raisons.

Premièrement parce que POSIX n’est pas l’implémentation d’un standard mais bien une spécification écrite en anglais. Elle peut donc être ambiguë5.

Deuxièmement parce que les diverse implémentations peuvent comporter des bugs. Leurs comportements pourraient donc diverger quand bien même on utilise un outil ayant le bon nom et la bonne option.

Troisièmement parce qu’il existe plusieurs versions de POSIX dans le temps. Même si c’est assez rare des, outils et des options peuvent être ajoutées. Depuis 2024 xargs inclu une option -0 raccord avec find -print0. Utiliser xargs -0 aujourd’hui et déclarer une dépendance à xargs posix serait correct mais pourrait être surprenant. Il faudrait donc préciser la date à partir de laquelle l’outil, tel qu’utilisé dans le logiciel, est conforme à la spécification POSIX. xargs -0 devrait donc être déclaré sous la forme xargs POSIX 2024.

Puisqu’au final on cherche à communiquer rapidement et efficacement de quelles API et quels algorithmes le logiciel dépend, une manière de complémenter cette déclaration pourrait être d’intégrer la description de notre environnement de test.

Spécifier l’environnement de test

S’il semble presque impossible d’identifier sans ambiguité un comportement précis d’un outil de la tradition Unix il est possible d’identifier les versions effectivement testées lors du développement.

Ma machine fonctionne sous debian 12. Les outils dont dépend protoclium sont tous packagés dans les archives officielles de dépôts debian. Le code utilisé lors du développement est :

$ apt show coreutils lowdown fzy make gawk dash |
    awk '/^Pack|^Vers/ { print $2 }' |
    paste -d':' - - |
    column -ts ':'
coreutils   9.1-1
lowdown     1.0.0-2
fzy         1.0-1
make        4.3-4.1
gawk        5.2.1-2
dash        0.5.12-2

Cette méthode s’approche de celle que l’on entend dans la bouche de certain·es informaticien·nes : “Je ne cible pas un standard mais une implémentation”. C’est d’autant plus pertinent que l’éventuel standard sur lequel on se repose n’est pas ou mal respecté. Cela dit d’expérience je n’ai jamais rencontré de divergences dans les fonctionnements des outils et options unix spécifiées dans POSIX mais je n’ai pas testé d’autres implémentations que celles de busybox, GNU et openBSD.

Les dépendances non logicielles

Lors d’une discussion avec Florent il est apparu évident que les dépendances, même assez directes, ne sont pas que logicielles. Il y aurait pèle mêle :

Le matériel

Déclarer les dépendances au matériel est déjà quelque chose de pratiqué dans certains domaines, par exemple celui du jeux vidéo. Puisqu’il est évident qu’il faille un ordinateur ce type de dépendance s’attelle à déclarer quel type d’ordinateur permettra de faire fonctionner le jeu tout court et très bien.

On peut ainsi voir sur des plateformes comme Steam6 :

Minimale :
    Système d'exploitation et processeur 64 bits nécessaires
    Système d'exploitation  *: Windows 7
    Processeur : Intel Core 2 Duo
    Mémoire vive : 2 GB de mémoire
    Graphiques : DirectX 11 compatible video card (integrated or dedicated with min 512MB memory)
    DirectX : Version 11
    Espace disque : 20 GB d'espace disque disponible

Recommandée :
    Système d'exploitation et processeur 64 bits nécessaires
    Système d'exploitation  *: Windows 7/8/10
    Processeur : Intel Core i7 or AMD 1800 equivalent
    Mémoire vive : 8 GB de mémoire
    Graphiques : NVIDIA Geforce 1060 or equivalent
    DirectX : Version 11
    Espace disque : 20 GB d'espace disque disponible

Au delà de ce domaine cette pratique est assez rare. On peut cependant constater des déclarations qui s’en rapprochent sous la forme des benchmarks, en particulier pour les logiciels de calcul intensif7. Si ces benchmarks ne sont pas présentés de la même manière que les dépendances logicielles on peut en induire une puissance minimale de matériel en deçà de laquelle le logiciel n’est, dans la pratique, plus fonctionnel.

Pour protocolium il serait possible de le tester sur du matériel peu puissant, confirmer qu’il y fonctionne correctement puis déclarer cette configuration comme celle minimale requise. En l’occurrence il fonctionne bien sur un raspberry pi zero v1.1 à savoir la configuration suivante faisant tourner debian 12 :

L’énergie

La dépendance à l’énergie est assez évidente et peut être induite de la dépendance au matériel, le matériel nécessitant de l’énergie pour fonctionner. Cela dit on peut tout de même noter plusieurs considérations à ce sujet.

En fonction du matériel nécessaire, de son efficacité et de la quantité de calculs effectués deux logiciels peuvent consommer des quantités radicalement différentes d’énergie. A grande échelle l’approvisionnement en énergie peut devenir un enjeux majeur nécessitant des mesures d’adaptation. Par exemple les alimentations des baies du datacenter de l’Université de Strasbourg ont été dimensionnées pour des hyperviseurs hébergeant des VM faisant tourner des applications de gestion. Résultat, le centre de calcul de l’Université de Strasbourg est contraint de mettre moins de serveur de calcul par baie que ce que leur volume permet puisqu’elle ne pourraient pas fournir suffisamment de puissance autrement. A plus grande échelle encore l’émergence des IA génératives incite leurs créateurs à construire des centrales proches des datacenters8. S’il est difficile de quantifier voir même formuler une dépendance à l’énergie pour les logiciels il est manifeste qu’ils ne façonnent pas tous leurs environnements de la même manière.

Histoire de l’usage et de la disponibilité constante ou pas d’énergie. Y réfléchir. TODO.

Les compétences

Même si l’on peut aspirer à produire du logiciel durable qui ne nécessiterait plus ou presque plus de modification il reste qu’il est souhaitable que les personnes qui utilisent un outil puissent le modifier. Si ce souhait est jugé primordiale on peut considérer qu’un critère nécessaire à l’adoption d’un outil est d’avoir, soit même ou proche de soit, les compétences pour. On peut envisager de caractériser cette nécessité comme une dépendance.

Cette compétence se décline au moins en deux parties, celle de comprendre l’outil tel qu’il existe et celle de pouvoir le modifier/y ajouter des choses. Certains outils s’architecturent de manière à pouvoir découpler ces deux compétences. Firefox, à travers son système de plugin, offre la possibilité à des personnes sachant écrire du javascript d’étendre les fonctionnalités de leur navigateur sans pour autant comprendre ou lire son code.

Le fait que “l’environnement d’exécution” de protocolium soit un script shell permet de ajouter aux sources n’importe quel langage du moment qu’il s’interface raisonnablement bien avec le reste du système Unix. On pourrait donc écrire que protocolium dépend d’une personnes sachant lire du shell, awk et des regex pour la compréhension et sachant écrire un langage de programmation pour l’extension. Dans les fait sa petite taille implique de devoir presque toujours à la fois comprendre le code existant et maitriser l’écriture de notre extension.

On pourrait donc écrire :

Pour modifier protocolium et y ajouter des fonctionnalités il faut une personne qui :

Durabilité

Je suis intéressé par l’idée de mesurer et de raconter9 la durabilité des logiciels. J’aimerais que ce que je produis dure longtemps et coûte peu à maintenir. Sont ici compris les coûts financiers, humains, environnementaux. Pour cela il faut que le logiciel remplissent aux moins trois principes, à savoir qu’il soit :

stable

J’entends par stable sa capacité à rendre service de la même manière dans le temps. Pour être stable il faut que le logiciel soit robuste au regard du changement de son environnement. Qu’il fonctionne à l’identique malgré le changement de matériel et le changement des logiciels qui l’entourent.

Pour cela se reposer sur un standard fondamental tel que POSIX est efficace mais pas magique. Si cette stratégie fonctionne c’est qu’elle déplace l’effort de maintenance du logiciel que l’on écrit vers d’autres. Cela pose des questions de dépendance aux conditions matérielles qui permettent de perpétuer les environnements logiciels qui respectent POSIX10. Cette question n’est pas anecdotique dans la mesure où POSIX est de taille et de complexité conséquente. Un système s’y conformant strictement serait certainement plus succint que les systèmes d’exploitation aujourd’hui largement distribués mais il n’empêche qu’il ne pourrait être facilement re-développé par une seule personne ou même un groupe restreint de personnes.

Cependant cela est vrai pour n’importe quel standard et d’autant plus pour ceux pour lesquels un système POSIX est un pré-requis. Si POSIX est cité plutôt favorablement dans ce document c’est qu’il est structurant et influent, techniquement culturellement et historiquement, un très grand nombre de systèmes.

réparable

Réparable désigne la capacité des personnes à réparer l’outil s’il n’est plus fonctionnel.

Il serait pertinent de distinguer différents aspects de la réparabilité. Un logiciel en C est possiblement très facile à réparer pour une personne compétente en C, très difficile pour une personne ne l’étant pas. Un outil peut être très facile à réparer pour la personne ou l’organisation l’ayant développé, très difficile pour les personnes l’utilisant. La ou les réparabilité·s dépend largement de son contexte. Il est possible qu’il faille faire des compromis entre plusieurs de ces aspects.

Remarque personnelle : j’aime penser qu’il faudrait favoriser la réparabilité par les personnes qui utilisent l’outil. Cela implique de prendre conscience des compétences et contraintes des utilisateurices. L’idéal restant que les personnes construisent leurs propres outils (type atelier paysan : “ça marche parce que y’avait pas d’ingénieur”11).

La réparabilité s’inscrit également dans le temps. Un outil utilisant une technologie très répandue à l’instant T sera peut-être moins réparable à l’instant T+1 si la technologie n’est presque plus pratiquée. Un groupe d’utilisateurice peut voir ses compétences ou son temps dédié à la réparation changer avec le temps au gré des arrivées et départs. Si l’on avait par exemple voulu juger de la réparabilité de protocolium dans le temps en imaginant qu’il eu été écrit dans le passé, une question pertinente serait : quelle technologie serait la plus susceptible d’être maîtrisée de manière continue à Commown sur les N dernières années ?”

S’il y a certainement des grandes tendances favorisant la réparabilité du logiciel (code libre, logiciel simple de taille réduite, documentation claire et exhaustive) son évaluation reste avant tout contextuelle.

portable

La portabilité désigne la capacité d’un logiciel à pouvoir fonctionner dans divers environnements logiciels et matériels. Peut-être que stable et portable sont les deux faces d’une même pièce, l’une à travers le temps, l’autre à travers des environnements divers ?

Un logiciel sera plus durable s’il étend l’ensemble des machines et systèmes d’exploitation sur lesquels il peut fonctionner sans ajustements particulier. Plusieurs stratégies, ne s’excluant pas, peuvent être utilisées : le recours à une machine virtuelle12, développer pour une stack technique extrêmement répandue dont le bon fonctionnement relève de l’intérêt de groupes très divers et puissants13, limiter les dépendances de façon à ne devoir porter que notre logiciel et pas toutes ses dépendances avec. À défaut de rendre possible l’exécution de l’outil nativement sur un nouveau système il est envisageable de rendre son usage possible à travers un tiers.

Dans certains cas les efforts de portabilité peuvent aider les efforts de stabilité et de réparabilité, notamment lorsque les systèmes visés ont un standard en commun. Tendre vers ce standard le rendra aussi souvent plus simple et mieux documenté14. Cette stratégie pourrait également permettre de justifier l’écartement de certaines dépendances ou techniques du logiciel lorsque des arguments plus politiques ou sociaux ne fonctionne pas : “si ce n’est pas dans le standard on l’utilise pas”.

A l’inverse il est possible qu’une grande portabilité implique une plus grande complexité. Si l’outil ne vise pas une machine virtuelle relativement simple et/ou s’il souhaite intégrer un grand nombre de fonctionnalités complexes, une grande portabilité implique d’intégrer davantage de code gérant les spécificités de chaque système. Dans le pire des scénarios cela revient à réécrire N fois l’outil pour N systèmes différents.


  1. Cox, Joel, Eric Bouwers, Marko van Eekelen, et Joost Visser. « Measuring Dependency Freshness in Software Systems ». 2015 IEEE/ACM 37th IEEE International Conference on Software Engineering 2 (mai 2015): 109‑18. https://doi.org/10.1109/ICSE.2015.140

  2. faut-il encore le montrer 

  3. et on le comprend bien, elles sont souvent très pratiques 

  4. j’ai pas d’exemple sous la main mais faîtes moi confiance svp 

  5. il existe un exemple dans les réponses de Stéphane Chazelas sur unix.stackexchange.com mais je ne sais plus laquelle 

  6. https://store.steampowered.com/app/632470/Disco_Elysium__The_Final_Cut/ 

  7. un peu la flemme de trouver un exemple, désolé 

  8. par exemple https://www.cnbc.com/2025/10/28/google-nextera-iowa-duane-arnold-nuclear-power-plant-ai-energy-demand-data-centers.html 

  9. les deux peuvent aller ensemble, ajouter le lien vers la conf quand sortie 

  10. plus ou moins puisqu’en réalité presque aucun système se conforme strictement à POSIX 

  11. citation entendue dans le film “Low-tech” 

  12. https://100r.co/site/uxn.html 

  13. en gros s’assurer que ça fonctionne sur linux, éventuellement sur d’autres Unix et windows 

  14. assez vrai pour les scripts shells. Ensuite ici “plus simple” est subjectif. Parfois reproduire une option d’un GNU coreutils en étant strictement POSIX peut donner du code alambiqué, du moins pour qui que ce soit qui se sera habitué au confort des coreutils (voir ce sed -i posix : https://raw.githubusercontent.com/aaronNGi/sed-i/refs/heads/main/sed.sh). Dans la pratique les éléments non POSIX particulièrement utiles sont généralement implémentés dans les Unix populaires (Linux, Macos, *BSD), par exemple mktemp. Si je dis ici que ça peut donner des trucs plus simples c’est en écartant les cas où l’on profite du confort supplémentaire apporté par les extensions à POSIX pour apporter significativement plus de fonctionnalités à notre outil. Ce n’est pas clair dans le paragraphe.